Po przeczytaniu Stephen Toub's article on SynchronizationContext ja zostaję z pytaniem o wyjściu tego kawałka kodu .NET 4.5:SynchronizationContext płynie na Task.Run ale nie czekają
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));
}
wyjście jest:
btnDoSomething_Click WindowsFormsSynchronizationContext
DoItAsync WindowsFormsSynchronizationContext
PerformServiceCall 1 WindowsFormsSynchronizationContext
PerformServiceCall 2 ThreadPoolTaskScheduler
ProcessMessage ThreadPoolTaskScheduler
PerformServiceCall 3 ThreadPoolTaskScheduler
Ale spodziewałbym PerformServiceCall 1, aby nie być na WindowsFormsSynchronizationContext ponieważ artykuł stwierdza, że „SynchronizationContext. Prąd nie "płynie" w oczekiwaniu na punkty "...
kontekst nie przejdzie Dzwoniąc PerformServiceCall z Task.Run i lambda asynchroniczny, tak:
await Task.Run(async() =>
{
await PerformServiceCall();
}).ConfigureAwait(false);
Może ktoś wyjaśnić lub punkt do pewnego dokumentacji na ten temat?
Wywołanie ConfigureAwait() nie będzie miało żadnego wpływu, dopóki zadanie faktycznie nie zacznie czekać. To się jeszcze nie stało, twoje wywołanie LogSyncContext() było wcześniej. Przenieś go po oczekiwaniu. –
Czy to nie jest zakleszczenie w 'DoItAsync(). Czekać();'? –
Nie, to nie jest zakleszczenie dzięki wywołaniu ConfigureAwait – Stif