After reading Stephen Toub's article on SynchronizationContext I'm left with a question about the output of this piece of .NET 4.5 code:
private void btnDoSomething_Click()
{
LogSyncContext("btnDoSomething_Click");
DoItAsync().Wait();
}
private async Task DoItAsync()
{
LogSyncContext("DoItAsync");
await PerformServiceCall().ConfigureAwait(false); //to avoid deadlocking
}
private async Task PerformServiceCall()
{
LogSyncContext("PerformServiceCall 1");
HttpResponseMessage message = await new HttpClient
{
BaseAddress = new Uri("http://my-service")
}
.GetAsync("/").ConfigureAwait(false); //to avoid deadlocking
LogSyncContext("PerformServiceCall 2");
await ProcessMessage(message);
LogSyncContext("PerformServiceCall 3");
}
private async Task ProcessMessage(HttpResponseMessage message)
{
LogSyncContext("ProcessMessage");
string data = await message.Content.ReadAsStringAsync();
//do something with data
}
private static void LogSyncContext(string statementId)
{
Trace.WriteLine(String.Format("{0} {1}", statementId, SynchronizationContext.Current != null ? SynchronizationContext.Current.GetType().Name : TaskScheduler.Current.GetType().Name));
}
The output is:
btnDoSomething_Click WindowsFormsSynchronizationContext
DoItAsync WindowsFormsSynchronizationContext
PerformServiceCall 1 WindowsFormsSynchronizationContext
PerformServiceCall 2 ThreadPoolTaskScheduler
ProcessMessage ThreadPoolTaskScheduler
PerformServiceCall 3 ThreadPoolTaskScheduler
But I would expect PerformServiceCall 1 to not be on the WindowsFormsSynchronizationContext since the article states that "SynchronizationContext.Current does not “flow” across await points"...
The context does not get passed when calling PerformServiceCall with Task.Run and an async lambda, like this:
await Task.Run(async () =>
{
await PerformServiceCall();
}).ConfigureAwait(false);
Can anyone clarify or point to some documentation on this?