Task.Delay永远不会完成

22
以下代码将永远被冻结。
public async Task DoSomethingAsync()
{
    await Task.Delay(2000);
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    DoSomethingAsync().Wait();
    // Task.Delay(2000).Wait();
}
如果我用被注释掉的代码替换调用DoSomethingAsync的代码,它会按预期工作。我怀疑嵌套的awaits在某种程度上导致了死锁,但我不确定原因,也不知道如何解决它。

1
可能是导致死锁的async/await示例的重复。 - Thomas Levesque
1个回答

45

假设 Button_ClickGUI 线程上运行,你可能会遇到死锁问题。

当你在任务上使用 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);
}

4
我用了将近3个小时才找到GUI线程异步等待Bug的原因……如果可以的话,我会给你两个赞! - Martin Booka Weser

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