【发布时间】:2018-02-24 09:20:09
【问题描述】:
我正在测试 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。
【问题讨论】:
-
ContinueWithis an extremely low-level plumbing method。您应该使用await而不是ContinueWith。
标签: c# asynchronous continuewith