c# - 任务 ContinueWith 行为中的异步?

标签 c# asynchronous async-await

你如何解释以下行为:

await Task.Run(() => { }).ContinueWith(async prev =>
{
    Console.WriteLine("Continue with 1 start");
    await Task.Delay(1000);
    Console.WriteLine("Continue with 1 end");
}).ContinueWith(prev =>
{
    Console.WriteLine("Continue with 2 start");
});

为什么我们会在“Continue with 1 end”之前得到“Continue with 2 start”?

最佳答案

下面的代码等同于您的示例,其中显式声明了变量,因此更容易看出发生了什么:

Task task = Task.Run(() => { });

Task<Task> continuation1 = task.ContinueWith(async prev =>
{
    Console.WriteLine("Continue with 1 start");
    await Task.Delay(1000);
    Console.WriteLine("Continue with 1 end");
});

Task continuation2 = continuation1.ContinueWith(prev =>
{
    Console.WriteLine("Continue with 2 start");
});

await continuation2;
Console.WriteLine($"task.IsCompleted: {task.IsCompleted}");
Console.WriteLine($"continuation1.IsCompleted: {continuation1.IsCompleted}");
Console.WriteLine($"continuation2.IsCompleted: {continuation2.IsCompleted}");

Console.WriteLine($"continuation1.Unwrap().IsCompleted:" +
    $" {continuation1.Unwrap().IsCompleted}");

await await continuation1;

输出:

Continue with 1 start
Continue with 2 start
task.IsCompleted: True
continuation1.IsCompleted: True
continuation2.IsCompleted: True
continuation1.Unwrap().IsCompleted: False
Continue with 1 end

棘手的部分是变量 continuation1 ,即 Task<Task> 类型. ContinueWith 方法不会自动解包 Task<Task>返回值如 Task.Run 确实如此,所以你最终会得到这些嵌套的任务。外层Task的工作只是创建内部 Task .当内Task已创建(未完成!),然后是外部 Task已经完成。这就是为什么 continuation2在内Task之前完成的 continuation1 .

有一个内置的扩展方法 Unwrap 这使得打开 Task<Task> 变得容易.一个展开的 Task当外部和内部任务都完成时,完成。打开 Task<Task> 的另一种方法是使用await运算符两次:await await .

关于c# - 任务 ContinueWith 行为中的异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58855484/

相关文章:

c# - SQL 中的字符串函数而不是 C#

c# - 继续不运行 C#

ios - Swift 延迟加载属性 Alamofire 请求

node.js - ASYNC/AWAIT 用于链接多个 http.requests

c# - 实现同步方法的异步版本 : How to return Task<int> which is constant 1?

javascript - 如何在原生 JavaScript 中重复调用异步方法直到成功?

c# - 使用中间件的聊天记录

c# - 用数组填充列表,列表中的所有数组都是相同的(在递归函数中)

c# - 发送带有附件 WinRT 的电子邮件

asynchronous - MeteorwrappAsync没有方法 'apply'