以下代码将永远冻结。
public async Task DoSomethingAsync()
{
await Task.Delay(2000);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DoSomethingAsync().Wait();
// Task.Delay(2000).Wait();
}
如果我使用注释掉的代码将调用切换到DoSomethingAsync
,它的行为符合预期。我怀疑嵌套的等待导致死锁,但我不确定原因,或者如何修复它。
答案 0 :(得分:28)
假设Button_Click
在GUI
主题中运行,你手上就会陷入僵局。
在任务上使用Wait
时,您将同步阻塞线程,直到任务结束,但任务永远不会结束,因为继续(Task.Delay(2000);
的完成)必须在GUI线程上运行同样(在Wait).
您有多种解决方案。使用ConfigureAwait(false)
来捕获GUI线程的SynchronizationContext:
public async Task DoSomethingAsync()
{
await Task.Delay(2000).ConfigureAwait(false);
}
或(我推荐)使用async void
事件处理程序(这是async void
方法的唯一合适位置):
private async void Button_Click(object sender, RoutedEventArgs e)
{
await DoSomethingAsync();
}
public async Task DoSomethingAsync()
{
await Task.Delay(2000);
}