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:
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;
}
}
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
.
I explain the details behind the deadlock scenario in my blog post Don't Block on Async Code.
Scenario one: you are sitting at your desk. There is an inbox. It is empty. A piece of paper suddenly arrives in your inbox describing a task. You jump to your feet and start running around doing the task. But what is the task? It says to do the following:
This workflow prevents you from getting work done because the last two steps are in the wrong order.
Scenario two: you are sitting at your desk. There is an inbox. It is empty. A piece of paper suddenly arrives in your inbox describing a task. You jump to your feet and start running around doing the task. But what is the task? It says to do the following:
What does the piece of paper you gave Debbie say? It says:
This workflow still is terrible in that (1) you are sitting there doing nothing while you wait for Debbie's alarm clock to go off, and (2) you are wasting the time of two workers when you could have a single worker do all the work. Workers are expensive.
But this workflow does not prevent you from getting work done eventually. It doesn't deadlock because you are not waiting on work that you yourself are going to do in the future, you are waiting for someone else to do the work.
(I note that this is not an exact analogy for what is happening in your program, but it is close enough to get the idea across.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With