Dopo aver letto Stephen Toub's article on SynchronizationContext sono lasciato con una domanda circa l'uscita di questo pezzo di .NET 4.5 Codice:SynchronizationContext scorre Task.Run ma non su attendono
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));
}
L'output è:
btnDoSomething_Click WindowsFormsSynchronizationContext
DoItAsync WindowsFormsSynchronizationContext
PerformServiceCall 1 WindowsFormsSynchronizationContext
PerformServiceCall 2 ThreadPoolTaskScheduler
ProcessMessage ThreadPoolTaskScheduler
PerformServiceCall 3 ThreadPoolTaskScheduler
Ma mi sarei aspettato PerformServiceCall 1 di non essere sul WindowsFormsSynchronizationContext in quanto l'articolo afferma che "SynchronizationContext. La corrente non "scorre" attraverso i punti di attesa "...
Il contesto non viene passato al momento della chiamata PerformServiceCall con Task.Run ed un lambda asincrona, in questo modo:
await Task.Run(async() =>
{
await PerformServiceCall();
}).ConfigureAwait(false);
Qualcuno può chiarire o punto in una certa documentazione su questo?
La chiamata ConfigureAwait() non avrà alcun effetto finché l'attività non inizia effettivamente ad attendere. Non è ancora successo, la tua chiamata a LogSyncContext() è stata anticipata. Spostalo dopo l'attesa. –
Non è quello stallo su DoItAsync(). Wait(); '? –
No, non è deadlocking grazie alla chiamata ConfigureAwait – Stif