2014-07-02 34 views
7

Poniższy kod zostanie zablokowany na zawsze.Task.Delay nigdy nie kończy się

public async Task DoSomethingAsync() 
{ 
    await Task.Delay(2000); 
} 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    DoSomethingAsync().Wait(); 
    // Task.Delay(2000).Wait(); 
} 

Gdybym przełączyć rozmowę do DoSomethingAsync z zakomentowanym kodzie, zachowuje się zgodnie z oczekiwaniami. Podejrzewam, że w jakiś sposób zagnieżdżone oczekiwania powodują impas, ale nie jestem pewien, dlaczego i jak to naprawić.

+0

możliwe duplikat [an asynchroniczny/przykład, że powoduje zakleszczenie oczekiwać] (http://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a -deadlock) –

Odpowiedz

22

Zakładając, że Button_Click działa w wątku GUI masz zakleszczenie na rękach.

Podczas korzystania z Wait dla zadania synchronicznie blokujesz wątek do momentu zakończenia zadania, ale zadanie nigdy się nie zakończy, ponieważ kontynuacja (zakończenie Task.Delay(2000);) musi również przebiegać w wątku GUI (który jest blokowany Wait).

masz kilka rozwiązań Albo użyć ConfigureAwait(false) nie uchwycić wątku GUI SynchronizationContext.

public async Task DoSomethingAsync() 
{ 
    await Task.Delay(2000).ConfigureAwait(false); 
} 

lub (którą polecam) użyć programu obsługi zdarzeń async void (który jest jedynym odpowiednim miejscem dla async void metoda):

private async void Button_Click(object sender, RoutedEventArgs e) 
{ 
    await DoSomethingAsync(); 
} 

public async Task DoSomethingAsync() 
{ 
    await Task.Delay(2000); 
} 
+1

Zajęło mi to prawie 3 godziny, aby znaleźć przyczynę błędu czekającego na wątek z gui. Czekałbym na dwie rzeczy, gdybym mógł! –

Powiązane problemy