I read this article about Task.ConfigureAwait
which can help to prevent deadlocks in async code.
Looking at this code: (I know I shouldn't do .Result
, But it's a part of the question)
private void Button_Click(object sender, RoutedEventArgs e)
{
string result = GetPageStatus().Result;
Textbox.Text = result;
}
public async Task<string> GetPageStatus()
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync("http://www.google.com");
return response.StatusCode.ToString();
}
}
This will result a deadlock because :
The
.Result
- operation will then block the current thread (i.e the UI thread) while it waits for the async operation to complete.Once the network call is complete it will attempt to continue executing the
response.StatusCode.ToString()
- method on the captured context. (which is blocked - hence deadlock).
One solution was to use :
var response = await httpClient.GetAsync("http://www.google.com").ConfigureAwait(false);
But other solution was to async all the way ( without blocking) :
/*1*/ private async void Button_Click(object sender, RoutedEventArgs e)
/*2*/ {
/*3*/ string result = await GetPageStatus();
/*4*/ Textbox.Text = result;
/*5*/ }
/*6*/ public async Task<string> GetPageStatus()
/*7*/ {
/*8*/ using (var httpClient = new HttpClient())
/*9*/ {
/*10*/ var response = await httpClient.GetAsync("http://www.google.com");
/*11*/ return response.StatusCode.ToString();
/*12*/ }
/*13*/ }
Question :
(I'm trying to understand how this code helps to solve the problem - via context POV).
Does line
#3
and line#10
captures different contexts?Am I right regarding the way of flow as I think it is:
line #3 calls #6 (which calls #10) and sees that it didn't finish yet, so it awaits ( captured context for #3 = UI thread).
Later on, line #10 capture another context (I will call it newContext) after it finishes, it is back to "newContext" and then releases the UI context(thread).
Was I right?
- Visualization: (is this the right flow?)