使用ConfigureAwait(false)仍然会导致异步/等待死锁吗?

3
根据这个链接,在特定情况下,使用async/await可能会导致死锁。
但是,如果我始终使用ConfigureAwait(false),是否仍然会发生死锁?
例如:task.ConfigureAwait(false).GetAwaiter().GetResult() 而不是:task.GetAwaiter().GetResult()

1
旁注:它是“configure await”,而不是“configure task”。在task.ConfigureAwait(false).GetAwaiter().GetResult()中的ConfigureAwait(false)没有任何影响,因为没有要配置的await - Stephen Cleary
3个回答

5

如果任何完成task或任何进一步的嵌套操作已经捕获了当前上下文并且该上下文绑定到特定线程,则仍然可能死锁,因为您正在使用该线程调用GetResult并阻塞,从而使其他人无法使用。

只需使用 await。正是await可以释放您当前的上下文。


4

是的,它仍然可能发生死锁,必须在所有嵌套的等待中实现ConfigureAwait(false),其中一些可能不受您控制。

最好的方法是不要依赖它,不要混合同步和async调用,让Async/Await自行传播。

确保它不会死锁(没有await)的唯一可靠方式(并具有争议性)是将其转移 / 包装到另一个任务并Wait该任务,或者在没有SynchronizationContext的框架中运行。


2
正如其名,ConfigureAwait()仅影响异步await。对于同步等待,如Task.Wait()Task.ResultTask.GetAwaiter().GetResult()则没有影响。 ConfigureAwait(false)的意思是大致为“我不关心代码在此异步等待后将在哪个线程上恢复执行”,因此,即使原始线程(更准确地说是SynchronizationContext)被某些东西阻塞了,它仍将继续在不同的线程上进行。但是,像GetAwaiter().GetResult()这样的同步等待永远不会切换线程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接