According to this link:
When you are awaiting on a method with await keyword, compiler generates bunch of code in behalf of you. One of the purposes of this action is to handle synchronization with the UI thread. The key
component of this feature is theSynchronizationContext.Current
which gets the synchronization context for the current thread.
SynchronizationContext.Current
is populated depending on the
environment you are in. TheGetAwaiter
method of Task looks up for
SynchronizationContext.Current
. If current synchronization context is not null, the continuation that gets passed to that awaiter will get posted back to that synchronization context.When consuming a method, which uses the new asynchronous language features, in a blocking fashion, you will end up with a deadlock if
you have an availableSynchronizationContext
. When you are consuming such methods in a blocking fashion (waiting on the Task with Wait method or taking the result directly from the Result property of the Task), you will block the main thread at the same time. When eventually the Task completes inside that method in the threadpool, it is going to invoke the continuation to post back to the main thread becauseSynchronizationContext.Current
is available and captured. But there is a problem here: the UI thread is blocked and you have a deadlock!
public class HomeController : Controller
{
public ViewResult CarsSync()
{
SampleAPIClient client = new SampleAPIClient();
var cars = client.GetCarsInAWrongWayAsync().Result;
return View("Index", model: cars);
}
}
public class SampleAPIClient
{
private const string ApiUri = "http://localhost:17257/api/cars";
public async Task<IEnumerable<Car>> GetCarsInAWrongWayAsync()
{
using (var client = new HttpClient())
{
var response = await client.GetAsync(ApiUri);
// Not the best way to handle it but will do the work for demo purposes
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<IEnumerable<Car>>();
}
}
}
I have trouble understanding the bolded part of the statement above, but when I test the code above, it deadlocks as expected. But I still can't understand why the UI thread is blocked?
In this case, what is the available SynchronizationContext
? Is it the UI thread?