我已经阅读了很多关于 async/await 编程模型的文章,但仍有一些不太清楚的地方,我想分享一下我对这些问题的困惑。

假设我们有以下配置:

主要的异步方法是 public async Task<bool> DoSomethingBigAsync(){...},它内部有 3 个其他方法,如下所示:

A) var a = await _someInstance.DoSomethingLittle_A_Async().ConfigureAwait(false);B) var b = await _someInstance.DoSomethingLittle_B_Async();C) var c = _someInstance.DoSomethingLittle_C();
比方说,从 UI 线程调用 main 方法。我们知道上下文将被捕获,当 main 方法完成时,上下文将被恢复。

如果我没记错的话,当第一个 ( A ) 异步方法被调用时,由于 ConfigureAwait(false) 的原因,UI 上下文不会被捕获,而是将延续从池中推送到一个线程。但这不能保证一定会发生,因为调用可能会立即完成。出于这个原因,我怀疑应该在所有内部异步方法上调用 ConfigureAwait(false)(在本例中为 A B )。这是正确的,还是运行时在看到对 ConfigureAwait(false) 的第一次调用后知道要做什么?

我的另一个担忧是关于两种不良做法(或认为如此)及其副作用。

根据 Stephen Toub 的文章,一种不好的做法似乎是:



出于这个原因,制作 DoSomethingLittle_C() 方法的异步版本并不是一个好主意。

另一个不好的做法似乎是:



现在,查看上面的代码,如果第一个 ConfigureAwait(false) 可以保证将延续推送到线程池,我将看不到使用 Task.StartNew(() => { c = _someInstance.DoSomethingLittle_C(); }) 的附加值。
另一方面,如果 ConfigureAwait(false) 从不保证将延续推送到线程池,那么我们可能会遇到问题,我们必须确保使用 Task.StartNew(() => { c = _someInstance.DoSomethingLittle_C(); })

错误的(?):
A) var a = await _someInstance.DoSomethingLittle_A_Async().ConfigureAwait(false);B) var b = await _someInstance.DoSomethingLittle_B_Async();C) var c = _someInstance.DoSomethingLittle_C();
正确的(?):
A) var a = await _someInstance.DoSomethingLittle_A_Async().ConfigureAwait(false);B) var b = await _someInstance.DoSomethingLittle_B_Async().ConfigureAwait(false);C) var c = Task.StartNew(() => {return _someInstance.DoSomethingLittle_C();});

最佳答案



是的。这应该。因为,正如您所说,前一个调用可能会同步完成,也因为前一个调用将来可能会更改,您不想依赖它。

关于 Task.Run (它比 Task.Factory.StartNew 更受欢迎),问题是是否在 API 的实现中使用它,答案几乎总是不。

你的情况不同。如果您在 UI 线程上并且您有大量工作(Stephen Cleary 的建议超过 50 毫秒)可以在后台完成,那么将这些工作卸载到 ThreadPool 线程以保持 UI 响应并没有错。就像 ConfigureAwait 一样,我不会依赖前面的调用将您移至 ThreadPool,因为它也可以同步完成。

所以,更正:

var a = await _someInstance.DoSomethingLittle_A_Async().ConfigureAwait(false);
var b = await _someInstance.DoSomethingLittle_B_Async().ConfigureAwait(false);
var c = await Task.Run(() => _someInstance.DoSomethingLittle_C()).ConfigureAwait(false);

关于c# - ConfigureAwait 和混合异步与同步调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31672308/

10-11 12:50