I prepared WinForms application to test if a one-line async method would cause a deadlock. button1_Click
event waits for GetZero
task awaited by one-line async proxy method. However, it causes deadlock. Why? I've read that one-line async method do not need to continue anything after await
completes, so there is no delegate to post to message pump causing deadlock.
For reference, button2_Click
event waits for the result of task GetZero
without proxy caller, and application works fine.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var zero = ProxyCallery().Result;
label1.Text += $"{zero}";
}
private void button2_Click(object sender, EventArgs e)
{
var zero = GetZero().Result;
label1.Text += $"{zero}";
}
private async Task<int> ProxyCallery()
{
return await GetZero();
}
private async Task<int> GetZero()
{
await Task.Delay(100).ConfigureAwait(false);
return await Task.FromResult(0);
}
}
Why is button1_Click
causing deadlock?
await Task.Delay(100).ConfigureAwait(false);
configures the await only for that call. It doesn't affect awaits that might depend on that particular one, such as the await GetZero()
in the ProxyCallery()
method.
That latter await is still going to require continuation in the UI thread, which you've blocked with ProxyCallery().Result
. Hence the deadlock.
I've read that one-line async method do not need to continue anything after await completes, so there is no delegate to post to message pump causing deadlock.
I don't know where you've read that, but it's false. The compiler doesn't try to optimize "tail awaits". In reality, even if the last thing in the method is an await
, there is still code to be executed on the continuation. At the very least, unwrapping any exception, but also propagating the continuation to the Task
represented by that async
method.
So there is no difference at all with respect to deadlock potential, or any other aspect of asynchronous execution, for await
statements that conclude a method as compared to await
statements found anywhere else in a method.