为什么这个代码在WinForm上死锁,但在ConsoleApplication中有效?

时间:2017-01-20 14:29:14

标签: c# .net async-await

考虑这个简单的async方法:

private static async Task<int> foo()
{
    await Task.Delay(1500);
    return 1;
}

如果我在WinForm应用程序中执行以下操作,正如我所料,它会死锁

private void Form1_Load(object sender, EventArgs e)
{
    var fooTask = foo();
    fooTask.Wait();
}

但是,如果我在ConsoleApplication中执行相同操作(不会死锁)

static void Main(string[] args)
{
    var fooTask = foo();
    fooTask.Wait();
}

为什么会这样? Task不能继续,因为上下文线程被“阻止”了吗?

1 个答案:

答案 0 :(得分:3)

因为WinForms应用程序有一个SynchronizationContext。这意味着,每当您等待异步操作时,操作将在同一个SynchronizationContext上继续(默认情况下)。

您可以通过调用不捕获SynchronizationContext的ConfigureAwait(false)来更改此行为。

在您的情况下,此SynchronizationContext用于UI线程。因此,当你执行

  

await Task.Delay(1500)

继续代码将在UI线程上执行。但与此同时,由于

,UI线程被阻止
  

fooTask.Wait()

但是,ConsoleApplications没有SynchronizationContext,因此可以在不同的线程上执行异步操作的继续。