使用ContinueWith时无法启动第二个操作

Iva*_*ono 14 c# asynchronous entity-framework async-await

我有一个循环,在循环内我正在做:

await Task.Delay(1000, ct).ContinueWith(async _ =>
{
    await SecondMethodAsync(ct);
});
Run Code Online (Sandbox Code Playgroud)

第二种方法使用 EF 获取实体,设置一些属性并通过await SaveChangesAsync()调用DbContext.

上面应该等待1s然后继续第二种方法。通过上述实现,我得到以下异常:

在上一个异步操作完成之前,第二个操作在此上下文上启动。使用“await”确保在此上下文上调用另一个方法之前所有异步操作已完成。不保证任何实例成员都是线程安全的。

当我将上面的内容更改为:

await Task.Delay(1000, ct);
await SecondMethodAsync(ct);
Run Code Online (Sandbox Code Playgroud)

一切正常。

上面的两个片段有什么区别?如何使第一个片段起作用?

tym*_*tam 12

摘自任务之旅,第 7 部分: async/await 大师Stephen Cleary的续篇:

总之,我根本不建议使用ContinueWith,除非您正在进行动态任务并行(这是极其罕见的)。在现代代码中,您几乎应该始终使用await 而不是ContinueWith。有几个好处等待着。

您知道解决方案并且非常棒:

await Task.Delay(TimeSpan.FromSeconds(1), ct);
await SecondMethodAsync(ct);
Run Code Online (Sandbox Code Playgroud)


Mic*_*lor 10

我认为原因如下。如果我错了,请纠正我。

async里面的 lambda返回ContinueWithTask这意味着ContinueWith实际上在它得到它之后就完成了Task(而不是在Task完成时)。程序流程直接进入下一个循环迭代并DBContext再次命中。

因此,以下内容也可能有效,因为 的返回类型ContinueWithTask<Task>

await await Task.Delay(1000, ct).ContinueWith(async _ => {
    await SecondMethodAsync(ct); 
});
Run Code Online (Sandbox Code Playgroud)