2014-07-02 5 views
7

Il seguente codice si bloccherà per sempre.Task.Delay non completa mai

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

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

Se posso passare la chiamata a DoSomethingAsync con il codice commentato, si comporta come previsto. Sospetto che in qualche modo l'attesa annidata stia causando un deadlock, ma non sono sicuro del perché o di come risolverlo.

+0

possibile duplicato [An asincrona/attendere esempio che causa un deadlock] (http://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a -deadlock) –

risposta

22

Supponendo che Button_Click funzioni nel thread GUI si ha un deadlock tra le mani.

Quando si utilizza Wait su un compito che si sta sincrono bloccando il filo finché l'attività termina, ma il compito sarà mai fine poiché la continuazione (il completamento Task.Delay(2000);) deve essere eseguito sul thread GUI pure (che viene bloccato sulla Wait).

sono disponibili diverse soluzioni sia per uso ConfigureAwait(false) di non catturare SynchronizationContext del thread GUI:.

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

O (che consiglio) utilizzare un gestore di async void evento (che è l'unico luogo appropriato per un async void metodo):

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

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

Mi ci sono voluti quasi 3 ore per trovare la causa di un baco gui-thread-attendi ... ti darei due ups se potessi! –