2015-09-03 12 views
8

Według najlepszych praktyk zaleca się używać .ConfigureAwait(false) z async/await słów kluczowych, jeśli można:Kiedy nie mogę używać ConfigureAwait (false)?

await Task.Run(RunSomethingAsync).ConfigureAwait(false); 

Czy możesz dać mi przykład sytuacji, kiedy nie można użyć .ConfigureAwait(false)? .

+3

Chodzi o to, kiedy powinieneś powrócić do kontekstu, z którego pochodzi, czyli do kanonicznego kontekstu interfejsu użytkownika. –

+0

@AdamHouldsworth w prawo, teraz ma to dla mnie idealny sens – Andrei

Odpowiedz

11

Ty „nie może” użycie ConfigureAwait(false) kiedy rzeczywiście dbają o kontekście synchronizacji jesteś w na przykład wyobrazić, co następuje w aplikacji GUI:

public async void SomeButtonClick(object sender, EventArgs e) 
{ 
    var result = await SomeAsyncOperation().ConfigureAwait(false); 
    textBox.Text = result; 
} 

Po powrocie z ConfigureAwait, ty nie powróci do wątku interfejsu użytkownika. To spowoduje, że InvalidOperationException.

1

Z source: Asynchronous .NET Client Libraries for Your HTTP API and Awareness of async/await's Bad Effects:

Gdy czekają na metodzie z kluczowych czekają, kompilator generuje wiązkę kodu w imieniu użytkownika. Jednym z celów tego działania jest obsługa synchronizacji z wątkiem interfejsu użytkownika (lub głównego). Kluczowym elementem tej funkcji jest SynchronizationContext.Current, który uzyskuje kontekst synchronizacji dla bieżącego wątku. SynchronizationContext.Current jest zapełniany w zależności od środowiska . Metoda GetAwaiter zadania wyszukuje dla SynchronizationContext.Current. Jeśli bieżący kontekst synchronizacji wynosi , nie ma wartości null, kontynuacja, która zostanie przekazana do tego oczekującego, zostanie zwrócona z powrotem do tego kontekstu synchronizacji.

Podczas używania metody, która używa nowego asynchronicznego języka, funkcje , w sposób blokujący, spowodujesz zakleszczenie, jeśli masz dostępny Kontekst Synchronizacji. Podczas konsumowania takich metod w sposób blokujący (czekając na metodę Zadanie z czekaniem lub biorąc wynik bezpośrednio z właściwości Wynik zadania ), zablokujesz główny wątek w tym samym czasie. Gdy ostatecznie zakończy się zadanie wewnątrz tej metody w wątku, to zamierza wywołać kontynuację, aby wysłać z powrotem do głównego wątku , ponieważ SynchronizationContext.Current jest dostępny i przechwycony. Ale jest tu problem: wątek interfejsu użytkownika jest zablokowany i masz impel !