让我以几句话开头这个问题:
Let me just preface this question with a few things:
因此,我确实知道这不是最佳做法,也不需要任何人告诉我.这更多是为什么要这样做"的问题.
So I do know that this is not a best practice, and don't need anyone telling me such. This is more of a "why does this work" question.
顺带一提,这是我的问题:
With that out of the way, here is my question:
我编写了一个小型的GUI应用程序,其中包含2个按钮和一个状态标签.其中一个按钮将在100%的时间内通过同步和异步来再现死锁问题.另一个按钮调用相同的异步方法,但它包装在一个Task中,该方法有效.我知道这不是一个好的编码习惯,但是我想了解为什么,它没有相同的死锁问题.这是代码:
I've written a small GUI application that has 2 buttons and a status label. One of the buttons will reproduce the deadlock issue with sync and async 100% of the time. The other button calls the same async method but it is wrapped in a Task, this one works. I know this is not a good coding practice, but I want to understand why it doesn't have the same deadlock issue. Here is the code:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async Task<string> DelayAsync() { await Task.Delay(1000); return "Done"; } private void buttonDeadlock_Click(object sender, EventArgs e) { labelStatus.Text = "Status: Running"; // causes a deadlock because of mixing sync and async code var result = DelayAsync().Result; // never gets here labelStatus.Text = "Status: " + result; } private void buttonWorking_Click(object sender, EventArgs e) { labelStatus.Text = "Status: Running"; string result = null; // still technically mixes sync and async, but works, why? result = Task.Run(async () => { return await DelayAsync(); }).Result; labelStatus.Text = "Status: " + result; } }推荐答案
它之所以有效,是因为buttonWorking_Click异步代码(DelayAsync以及传递给Task.Run的async lambda)没有当前的SynchronizationContext,而buttonDeadlock_Click异步代码(DelayAsync)可以.您可以通过在调试器中运行并观看SynchronizationContext.Current来观察差异.
It works because the buttonWorking_Click async code (DelayAsync as well as the async lambda passed to Task.Run) does not have a current SynchronizationContext, whereas the buttonDeadlock_Click async code (DelayAsync) does. You can observe the difference by running in the debugger and watching SynchronizationContext.Current.
我会在我的博客文章不要解释死锁情况背后的细节阻止异步代码.
更多推荐
将异步/等待与结果混合
发布评论