C# 链式ContinueWith不等待上一个任务完成

2024-01-20

我正在测试 C# async/await 的异步性,并发现了一个惊喜,ContinueWith 的后续代码不会等待上一个任务完成:

public async Task<int> SampleAsyncMethodAsync(int number,string id)
  {
            Console.WriteLine($"Started work for {id}.{number}");
            ConcurrentBag<int> abc = new ConcurrentBag<int>();

            await Task.Run(() => { for (int count = 0; count < 30; count++) { Console.WriteLine($"[{id}] Run: {number}"); abc.Add(count); } });

            Console.WriteLine($"Completed work for {id}.{number}");
            return abc.Sum();
        }

使用以下测试方法执行:

        [Test]
        public void TestAsyncWaitForPreviousTask()
        {
            for (int count = 0; count < 3; count++)
            {
                int scopeCount = count;

                var c = SampleAsyncMethodAsync(0, scopeCount.ToString())
                .ContinueWith((prevTask) =>
                {
                    return SampleAsyncMethodAsync(1, scopeCount.ToString());
                })
                .ContinueWith((prevTask2) =>
                {
                    return SampleAsyncMethodAsync(2, scopeCount.ToString());
                });
            }
        }

输出显示运行 0.0、1.0 和 2.0 的执行正确地异步执行,但后续的 x.1 和 x.2 几乎立即开始,并且 x.2 实际上在 x.1 之前完成。例如。如下记录:

[2] Run: 0
[2] Run: 0
[2] Run: 0
Completed work for 2.0
Started work for 0.1
Started work for 0.2  <-- surprise!
[0] Run: 2
[0] Run: 2
[0] Run: 2
[0] Run: 2
[0] Run: 2

看起来 continueWith 只会等待第一个任务 (0),而不管后续的链如何。 我可以通过将第二个ContinueWith 嵌套在第一个Continuewith 块中来解决该问题。

我的代码有问题吗?我假设 Console.WriteLine 尊重 FIFO。


简而言之,您期望ContinueWith等待先前返回的对象。返回一个对象(甚至是一个Task) in ContinueWithaction 对返回值不执行任何操作,它不会等待它完成,它会返回该值并传递给延续(如果存在)。

确实会发生以下情况:

  • You run SampleAsyncMethodAsync(0, scopeCount.ToString())
  • 完成后,执行延续 1:

    return SampleAsyncMethodAsync(1, scopeCount.ToString());
    

    当它偶然发现await Task.Run,它返回一个任务。即,它不会等待 SampleAsyncMethodAsync 完成。

  • 然后,延续 1 被认为已完成,因为它返回了一个值(任务)
  • 运行延续 2。

如果您手动等待每个异步方法,那么它将相应地运行:

for (int count = 0; count < 3; count++)
{
    int scopeCount = count;

    var c = SampleAsyncMethodAsync(0, scopeCount.ToString())
    .ContinueWith((prevTask) =>
    {
        SampleAsyncMethodAsync(1, scopeCount.ToString()).Wait();
    })
    .ContinueWith((prevTask2) =>
    {
        SampleAsyncMethodAsync(2, scopeCount.ToString()).Wait();
    });
}    

Using ContinueWith(async t => await SampleAsyncMethodAsync...效果不太好,因为它会导致包裹Task<Task>结果(解释得很好here https://stackoverflow.com/questions/18697167/use-an-async-callback-with-task-continuewith).

另外,您还可以执行以下操作:

for (int count = 0; count < 3; count++)
{
    int scopeCount = count;

    var c = SampleAsyncMethodAsync(0, scopeCount.ToString())
        .ContinueWith((prevTask) =>
        {
            SampleAsyncMethodAsync(1, scopeCount.ToString())
                .ContinueWith((prevTask2) =>
                {
                    SampleAsyncMethodAsync(2, scopeCount.ToString());
                });
        });   
}

然而,它创建了某种回调地狱并且看起来很混乱。

您可以使用await使这段代码更简洁:

for (int count = 0; count < 3; count++)
{
    int scopeCount = count;

    var d = Task.Run(async () => {
        await SampleAsyncMethodAsync(0, scopeCount.ToString());
        await SampleAsyncMethodAsync(1, scopeCount.ToString());
        await SampleAsyncMethodAsync(2, scopeCount.ToString());
    });
}   

现在,它运行 3 个任务进行 3 次计数,每个任务将因此运行异步方法number等于 1、2 和 3。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 链式ContinueWith不等待上一个任务完成 的相关文章

  • 运行 t4 脚本作为 resx 文件的自定义工具

    我有一个资源文件MyResource resx 我想改变MyResource Designer cs文件生成 我有一个 t4 脚本 它接受 resx 文件作为输入并给出结果转换 但是 我必须手动运行此 t4 才能使其工作 我看到 resx
  • 对静态成员变量的未定义引用

    我有一个有静态成员的类 它也是我的程序中其他几个类的基类 这是它的头文件 ifndef YARL OBJECT HPP define YARL OBJECT HPP namespace yarlObject class YarlObject
  • 如何动态加载包含非托管代码的原始程序集?(绕过“无法验证的代码失败策略检查”异常)

    我将举一个使用的例子系统 Data SQLite DLL http sqlite phxsoftware com 这是一个包含非托管代码的混合程序集 如果我执行这个 var assembly Assembly LoadFrom System
  • 如何在线程创建和退出时调用函数?

    include
  • WP8.1 C# 绑定联系人图像

    信息很简单 我正在尝试创建一个可以显示用户联系人的应用程序 我也是一名自学成才的程序员 所以我在某些方面有编程经验 但总体来说我对数据绑定相对较新 首先 我有一个 ListView 控件 其中包含图像绑定
  • 在调用堆栈中看到大量 clr!CLR Semaphore::Wait

    我们看到很多像下面这样的调用堆栈 我可以知道什么条件 情况会发生这种情况吗 OS Thread Id 0x48654 559 Current frame ntdll NtWaitForSingleObject 0xa Child SP Re
  • 每次调用新方法时触发事件

    我正在做一个logger for a c 应用程序需要记录每个方法被调用的时间以及每个方法执行时间 我可以通过调用自己的方法来做到这一点EventLogger LogMethodCall方法在每个方法的开头 但我想知道是否有办法使CLR每次
  • 在不使用 ncurses 的情况下用 C/C++ 编写“真正的”交互式终端程序,例如 vim、htop...

    不 我不想使用ncurses 因为我想了解如何 终端可以工作 并且我自己编程也很有趣 没有 必须是可移植的 它必须只能在基于 linux xterm 的终端仿真器上工作 我想做的是编写一个交互式终端应用程序 例如 htop 和 vim 我的
  • 无缝滚动瓷砖地图

    我正在开发一个自上而下的角色扮演游戏 并且想要实现无缝滚动地图 也就是说 当玩家探索世界时 地图之间没有加载屏幕 也没有通往下一个区域的 门 我有两种方法可以打破世界 在顶层 我有 区域 它只是 9 个 地图 的集合 这些区域仅由目录表示
  • 使用 size_t 值反向遍历向量

    我想以相反的方向遍历向量的值 如您所知 向量的大小为 size t 当我使用以下代码时 for size t r m size 1 r gt 0 r x r f r for size t c r 1 c lt m size c x r m
  • 求一个数的因数。无法得到准确的结果

    有人可以帮助纠正我的算法吗 我已经对几个数字进行了测试 但它没有输出完整的因式分解 对于具有大量因子的数字 它完全失败 int num 20 for int i 2 i lt num i if num i 0 cout lt lt i lt
  • C for 循环索引:新 CPU 中的前向索引更快吗?

    在我订阅的邮件列表上 两位知识渊博的 IMO 程序员正在讨论一些优化的代码 并说了以下内容 在 5 8 年前发布的 CPU 上 向后迭代 for 循环稍微快一些 e g for int i x 1 i gt 0 i 因为比较i归零比将其与其
  • 使用 INotifyPropertyChanged

    有人可以解释一下为什么在 wpf 中使用绑定时需要使用 INotifyPropertyChanged 的 实现吗 我可以在不实现此接口的情况下绑定属性吗 例如我有代码 public class StudentData INotifyProp
  • python 中的异步编程

    python 中有异步编程的通用概念吗 我可以为一个函数分配一个回调 执行它并立即返回主程序流 无论该函数的执行需要多长时间吗 您所描述的 主程序流程在另一个函数执行时立即恢复 不是通常所说的 异步 又名 事件驱动 编程 而是 多任务 又名
  • 按值返回的函数的返回语句中的初始化

    我的问题源于深入研究std move in return语句 例如以下示例 struct A A std cout lt lt Constructed lt lt this lt lt std endl A A noexcept std c
  • printf() 使用字符串表“解码器环”调试库

    我写这封信是想看看你们中是否有人见过或听说过我即将描述的想法的实现 我有兴趣为嵌入式目标开发 printf 风格的调试库 目标非常遥远 并且我和目标之间的通信带宽预算非常紧张 因此我希望能够以非常有效的格式获取调试消息 通常 调试语句如下所
  • SQL参数化查询不显示结果

    我的 DataAcess 类中有以下函数 但它没有显示任何结果 我的代码如下 public List
  • 未找到 _sqlite3_open 等符号错误

    您好 我收到此错误 Undefined symbols sqlite3 open referenced from main in ccRlWVer o sqliite3 close referenced from main in ccRlW
  • C# amo 获取角色完整

    我正在开发一个 SSAS 项目 其中除其他事项外 我需要获取 C 中表格多维数据集的完整用户列表 目前我让它以这样的方式工作 我可以获得角色 但数据不完整 当我调用 Server Database Roles 为了便于阅读而简化 属性并枚举
  • 如何在用户空间程序中使用内核 libcrc32c (或相同的函数)?

    我想在我自己的用户空间程序中进行一些 CRC 检查 我发现内核加密库已经在系统中 并且支持 SSE4 2 我尝试直接 include

随机推荐

  • 颁发身份超级账本作曲家时授权失败

    我阅读了建议检查 docker yaml 的答案 文件路径如下 我确认用户名是admin 密码是adminpw 不幸的是我仍然收到授权失败错误 我用来发布身份的命令 composer identity issue n trade netwo
  • 如何以 1 秒的间隔更新组件?

    我在戴尔面试时被问到这个问题 new Date 给你一个Date使用当前日期 时间初始化的对象 假设我的屏幕右上角显示当前时间 并且有人这样做了
  • InApp 计费验证 Web 服务器 PHP 上的订单

    我正在使用一个简单的 PHP 脚本来验证 Android 订单以解析客户的下载 receipt GET purchaseData billInfo json decode receipt true signature GET dataSig
  • stack --nix build 抱怨 ghc 版本不匹配

    在 NixOS 上构建 Threepenny gui 时stack nix build 我收到错误消息 说我的 ghc 版本错误 然后我尝试了stack nix setup 它不会运行 因为 bash 位于 NixOS 上的意外路径上 这是
  • Matlab 2012a Mex 在 Mountain Lion 上与 Xcode 4.5 配合使用

    我安装了 Mountain Lion 并安装了 Xcode 4 5 和 Matlab 2012a 我安装并运行了 MathWorks 网站上提供的补丁 但仍然收到以下错误 Applications MATLAB R2012a app bin
  • 在 iOS 8 上点击或选择输入字段中的所有内容时,光标超出边框

    IOS8有这个问题 IOS7没有 我有一个输入标签 其内容的长度大于其宽度
  • MMC进程立即关闭,无法链接到Windows窗体

    我想做的最终目标是将 MMC Microsoft 管理控制台 计算机管理管理单元 compmgmt msc 进程嵌入到 Windows 窗体中 或者将其视为模态弹出窗口的解决方法上菜单 现在 我只是想让 mmc exe 本身正常工作 然后再
  • 为什么应该在 LINQ To SQL 存储库保存方法中使用 GetOriginalEntityState()?

    我正在查看 Steven Sanderson 的 Pro ASP NET MVC 2 Framework 一书中的产品存储库中的保存方法示例 public void SaveProduct Product product if new pr
  • Google Cloud SQL 实例无响应,如何获得支持?

    当谈到数据库时 我们希望将管理它们的工作交给专业人士 这就是为什么我们选择 CloudSQL 第二代数据库实例形式的托管解决方案 今天实例停止响应 我单击了重新启动 它已经重新启动了几个小时并且没有响应 我尝试克隆实例 也没有响应 我不知道
  • Rails 3.2 和phonegap

    我当前正在运行一个rails应用程序 我想为其制作一个移动应用程序 我不想学习objective c或java 我读了很多关于phonegap的文章以及如何使用它来制作跨平台Web应用程序 Phonegap编译css htm js Rail
  • 如何在mvc4中区分连接等的调试和发布

    所以我对 MVC4 相当陌生 很多模式对我来说都是新的 然而 我好奇的一件事是关于发布 调试模式的最佳实践 对我来说 实时模式和调试模式之间有很多不同的事情 我希望所有这些都是自动的 这样我就不需要更改任何内容来发布 例如 我在我的存储库
  • 使用 sed 从变量中删除模式

    我正在使用一个脚本 该脚本有一个名为PRODUCT VERSION 该版本带有一个点 例如6 0 我需要删除点并将结果保存在另一个变量中 到目前为止我已经做到了 但它不能正常工作 PRD VER sed s PRODUCT VERSION
  • 从字符串数组创建字符串。最快的方法?

    我有一个字符串数组 A 到 E 我想将它们连接成一个字符串 A B C D E 我应该循环遍历数组还是使用 Join 函数 Dim MyArray 5 as String Dim MyString as String MyArray 1 A
  • 如何从网页添加事件到iCal / Outlook / Gmail?

    包含下载 ics iCal 文件的链接吗 通过电子邮件附加 ics 文件 如何构建文件 哪里可以找到规格 将hCalendar中的数据渲染到页面上有什么好处 那么搜索引擎可以以某种方式索引它吗 Thanks 你的问题的第一部分在谷歌上似乎有
  • PL/SQL中如何使用ifexists-ifnotexists?

    我正在尝试将 ifexists 语句从 SQL Server 转换为 PL SQL 但出现错误 我正在尝试检查是否NAME 1我的中不存在table 1 如果它们不存在 那么我正在检查是否COLUMN NAME NAME 2 存在于我的ta
  • 如何使用 REST API 在 keycloak 中重置用户密码

    我想对我的 Keycloak 服务器进行休息调用 根据文档 这应该很容易 https www keycloak org docs api 10 0 rest api index html executeactionsemail https
  • 支持的视频尺寸 MediaRecorder API android

    我正在尝试使用 mediarecorder 和 mediaprojection api 记录屏幕内容 当我尝试在设备上将视频更改为高清时 录制失败 但在 640 x 480 分辨率下工作正常 所以我的问题是如何获得特定设备上支持的视频分辨率
  • Ionic 模拟 android ERR_CONNECTION_REFUSED localhost:8100

    我尝试在 Android 上模拟我的 Ionic 应用程序 一旦我的应用程序在模拟设备中启动 它就会中断并出现以下错误 应用程序错误 净 ERR CONNECTION REFUSED http 本地主机 8100 http localhos
  • 有没有更好的方法在 C# 中创建深克隆和浅克隆?

    我一直在为一个项目创建对象 在某些情况下我必须为此对象创建深层副本 我想出了使用 C 的内置函数 MemberwiseClone 困扰我的问题是 每当我创建一个新类时 我就必须编写一个像下面的代码这样的函数来进行浅拷贝 有人可以帮我改进这部
  • C# 链式ContinueWith不等待上一个任务完成

    我正在测试 C async await 的异步性 并发现了一个惊喜 ContinueWith 的后续代码不会等待上一个任务完成 public async Task