C# 配置等待和GetWaiter更改行为
我正在试验各种任务。 我有 我希望最后一行没有死锁和崩溃,因为没有UI上下文,如果我没有使用GetWaiter(),我会遇到死锁 下一步: 在这里,由于非UI上下文,我预计最后一行会崩溃,但它可以正常工作。C# 配置等待和GetWaiter更改行为,c#,task,C#,Task,我正在试验各种任务。 我有 我希望最后一行没有死锁和崩溃,因为没有UI上下文,如果我没有使用GetWaiter(),我会遇到死锁 下一步: 在这里,由于非UI上下文,我预计最后一行会崩溃,但它可以正常工作。 当我们使用GetAwaiter()时,ConfigureAwait(false)是否有意义?ConfigureAwait在同一表达式中配置await关键字的行为。它不会影响其他方法中的其他await语句,如果不使用await,则不会产生任何效果 它控制await语句是否捕获当前同步上下文(如
当我们使用GetAwaiter()时,ConfigureAwait(false)是否有意义?
ConfigureAwait
在同一表达式中配置await
关键字的行为。它不会影响其他方法中的其他await
语句,如果不使用await
,则不会产生任何效果
它控制await
语句是否捕获当前同步上下文(如果有)。实际上,如果在UI线程上运行await
语句,则await任务
也将在UI线程上的等待
之后运行代码,而等待任务。ConfigureAwait(false)
将在线程池线程上的等待
之后运行代码
在您的第一个示例中:
private async Task<string> GetStringWithInnerCallConfigureAwaitFalseAsync()
{
await Task.Delay(3000).ConfigureAwait(false);
return "Finished!"; // <-- Run on the thread pool
}
private async Task<string> GetStringAsync()
{
await Task.Delay(3000);
return "Finished!"; // <-- Run on the captured SynchronizationContext (if any)
}
调用ConfigureAwait
在这里什么也不做,因为您没有等待结果。您可以不做任何更改就将其删除
var result = task.GetResult(); // deadlock
运行GetStringAsync
中的return
语句需要UI线程。由于在调用GetResult()
时阻止了它,因此它无法完成GetStringAsync
方法,因此出现了死锁
在调用
GetStringWithInnerCallConfigureAwaitFalseAync
的第二个代码段中:
var task = GetStringAsync().ConfigureAwait(false).GetAwaiter();
var task = GetStringWithInnerCallConfigureAwaitFalseAsync().ConfigureAwait(false).GetAwaiter();
同样,对ConfigureAwait(false)
的调用不起任何作用,因为您没有等待结果
var result = task.GetResult(); // No deadlock
这一次,getStringWithInnerCallConfigureAwaitFalseAync
不执行await…ConfigureAwait(false)
,因此await
之后的代码在线程池上运行,而不是在UI线程上运行。因此,不需要UI线程来完成此方法,因此您可以安全地(!)阻止它
Button11.Content = result; // No crash
您在UI线程上调用了此方法,并且从未离开过它-您同步调用所有内容,没有
wait
s等。因此,此时您仍在UI线程上谢谢,解释得很好!关键短语是,如果您不使用wait,它将无效。
var task = GetStringWithInnerCallConfigureAwaitFalseAsync().ConfigureAwait(false).GetAwaiter();
var result = task.GetResult(); // No deadlock
Button11.Content = result; // No crash