你如何解释以下行为:
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/