Blocking on async code can cause deadlocks C# with Example



Blocking on async code can cause deadlocks C# with Example

It is a bad practice to block on async calls as it can cause deadlocks in environments that have a synchronization 
context. The best practice is to use async/await "all the way down." For example, the following Windows Forms code 
causes a deadlock: 
private async Task TryThis() 
{ 
Trace.TraceInformation("Starting TryThis"); 
await Task.Run(() => 
{ 
Trace.TraceInformation("In TryThis task"); 
for (int i = 0; i < 100; i++) 
{ 
// This runs successfully - the loop runs to completion 
Trace.TraceInformation("For loop " + i); 
System.Threading.Thread.Sleep(10); 
} 
}); 
// This never happens due to the deadlock 
Trace.TraceInformation("About to return"); 
return true; 
} 
// Button click event handler 
private void button1_Click(object sender, EventArgs e) 
{ 
// .Result causes this to block on the asynchronous call 
bool result = TryThis().Result; 
// Never actually gets here 
Trace.TraceInformation("Done with result"); 
} 
Essentially, once the async call completes, it waits for the synchronization context to become available. However, 
the event handler "holds on" to the synchronization context while it's waiting for the TryThis() method to 
complete, thus causing a circular wait. 
To fix this, code should be modified to 
private async void button1_Click(object sender, EventArgs e) 
{ 
bool result = await TryThis(); 
Trace.TraceInformation("Done with result"); 
} 
 

Note: event handlers are the only place where async void should be used (because you can't await an async void 
method). 
 

Async-Await 

0 Comment's

Comment Form

Submit Comment