在提出问题之前,我想先说几句话:
- 我已经阅读了几篇 Stack Overflow 的文章,指出你不应该这样做(例如如何安全地混合同步和异步代码)。
- 我阅读了异步编程最佳实践,这篇文章也说你不应该这样做。
所以我知道这不是最佳实践,也不需要别人告诉我这一点。这更像是一个“为什么会这样工作”的问题。
那么问题来了:
我编写了一个小的图形用户界面应用程序,其中有2个按钮和一个状态标签。其中一个按钮会100%复现同步和异步死锁问题。另一个按钮调用相同的异步方法,但它被包装在一个任务中,这能够正常运行。我知道这不是一个好的编码实践,但我想了解为什么它没有相同的死锁问题。以下是代码:
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;
}
}