使用async / await时,如何在Win Forms构造函数中修复此死锁?

时间:2013-08-07 15:40:17

标签: c# .net task-parallel-library deadlock async-await

这是我的最低代表案例:

public Form1()
{
    Task.Delay(100).Wait();  // Works just fine

    this.Await().Wait();     // Blocks indefinitely
}

private async Task Await()
{
    await Task.Delay(100);
}

这里发生了什么?为什么这两个表现不一样?我该怎么做才能使后一个工作?

我的实际案例不那么简单,我不能“只使用第一个选项”。

1 个答案:

答案 0 :(得分:5)

您看到了我描述on my blogin an MSDN article的典型死锁情况。简而言之,在await完成后,async方法尝试在UI线程上恢复,您已通过调用Wait来阻止该线程。

要解决此问题,您最好一直使用async(即永远不要阻止async代码)。构造函数在这里构成了一个难点(因为它们不能是async);我探索了几个选项on my blog。正确的选项取决于您的代码库,但如果可能,我建议使用async工厂方法。选项包括:

  • 异步工厂方法。
  • 异步延迟初始化。
  • 异步初始化模式。

如果您绝对无法使用我在博客上描述的其中一个选项,那么您可以在所有ConfigureAwait(false)方法中使用async,然后使用Wait()来解决此问题。不会死锁。但是,这些在这些异步方法调用期间阻塞UI线程(这种方式首先使它们失去async的目的......)