R
Richard.Haggard
Guest
I recently wrote some code that used async/await and it deadlocked which served to show me that I didn't understand async/await technology well enough. Can someone please explain to me what's happening under the covers when a separate Task begins asynchronous operations, what happens to the caller when it hits the await, why the thread can continue to execute even though the thread is paused at the await and what happens when the asynchronous code completes and satisfies the await condition.
Here's an example of code that, according to the source, would cause a deadlock. Most explanations I've seen for why this deadlock happens is that the context is not available so the called method cannot complete and the caller can't release the context because it is waiting for the called method to complete. This sounds like something that would be said by someone who understands deadlocks but doesn't understand the underlying mechanism is in this case. There have be a few instances that give a slightly different explanation, that the async operation at the end of the chain needs to post an event that would be processed by the thread's message pump and would let the caller know that the async has completed but the thread's message pump has been blocked because further up the chain an async function was called synchronously. The idea of a non-foreground non-UI thread having a message pump is a concept that I'd not been exposed to before and I'm not sure that I'm understanding things correctly. So without further ado, here's the sample bad code. Let's discuss what is happening and why it deadlocks.
public void Button_Click()
{
var task = GetTextAsync("/path/to/file.txt");
// Dead lock here.
var result = task.Result;
this.SomeTextControl.Text = result;
}
public static async Task<string> GetTextAsync(string filePath)
{
using (var stream = System.IO.File.OpenRead(filePath))
{
using (var reader = new System.IO.StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}
}
Richard Lewis Haggard
Continue reading...
Here's an example of code that, according to the source, would cause a deadlock. Most explanations I've seen for why this deadlock happens is that the context is not available so the called method cannot complete and the caller can't release the context because it is waiting for the called method to complete. This sounds like something that would be said by someone who understands deadlocks but doesn't understand the underlying mechanism is in this case. There have be a few instances that give a slightly different explanation, that the async operation at the end of the chain needs to post an event that would be processed by the thread's message pump and would let the caller know that the async has completed but the thread's message pump has been blocked because further up the chain an async function was called synchronously. The idea of a non-foreground non-UI thread having a message pump is a concept that I'd not been exposed to before and I'm not sure that I'm understanding things correctly. So without further ado, here's the sample bad code. Let's discuss what is happening and why it deadlocks.
public void Button_Click()
{
var task = GetTextAsync("/path/to/file.txt");
// Dead lock here.
var result = task.Result;
this.SomeTextControl.Text = result;
}
public static async Task<string> GetTextAsync(string filePath)
{
using (var stream = System.IO.File.OpenRead(filePath))
{
using (var reader = new System.IO.StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}
}
Richard Lewis Haggard
Continue reading...