2012-08-09 11 views
11

ho bisogno di chiamare un metodo che restituisce un Task dall'internoPrevenire un deadlock quando si chiama un metodo asincrono senza utilizzare await

public override void OnActionExecuting(ActionExecutingContext filterContext) 

E non lo lascerà rendere questo metodo asincrono getta il seguente

Un modulo o gestore asincrono è stato completato mentre un'operazione asincrona era ancora in sospeso.

e quando si chiama

entityStorage.GetCurrentUser().Result 

ottengo una situazione di stallo. Come posso evitare questo?

Ho giocato intorno con esso fino a venire con roba come

entityStorage.GetCurrentUser().Result.ConfigureAwait(false).GetAwaiter().GetResult(); 

Ma questo non sta funzionando. Come posso farlo? La mia soluzione dovrà funzionare con ASP.NET 4 e il pacchetto di targeting asincrono, non posso utilizzare ASP.NET 4.5 mentre sto eseguendo la distribuzione in Azure.

+0

Trovato una risposta qui http://stackoverflow.com/a/5097066/168012 se qualcuno ha una soluzione migliore per favore condividere – Tom

+2

Stai derivando da 'AsyncController' invece di' Controller'? –

+0

Si prega di [votare qui] (https://aspnet.codeplex.com/workitem/9582) per consentire al team MVC di aggiungere il supporto per i filtri di azione 'async'. –

risposta

2

Poiché attendere è solo lo zucchero di sintassi per il compilatore che riscrive una continuazione per te, il percorso più "diretto" sarebbe quello di prendere qualsiasi codice seguisse la tua attesa e renderlo una chiamata ContinueWith.

Quindi, qualcosa di simile:

entityStorage.GetCurrentUser().ContinueWith(t => 
{ 
    // do your other stuff here 
}); 
12

La causa del deadlock è explained here. In breve, non bloccare il codice async. È necessario utilizzare ConfigureAwait(false) nella libreria codice async e await i risultati (non utilizzare Result o Wait).

Aggiornamento: Si prega divote here per la squadra MVC per aggiungere il supporto per async filtri d'azione.

+0

Ho difficoltà a trovare il link/pagina che dice così, ma altri mi hanno detto in passato che se si fornisce un collegamento (specialmente uno esterno a SO) che si dovrebbero copiare i bit chiave nella SO risposta. È un po 'menzionato qui, però, FWIW: http://meta.stackexchange.com/questions/118582/what-is-an-acceptable-answer –

+0

Sei corretto; la meta domanda a cui ti stai riferendo è stata recentemente eliminata come parte della strategia "facciamo un posto migliore". Tuttavia, come ha commentato Jon Skeet: se conosco la risposta e ho solo il tempo di pubblicare un link, è meglio di niente. –

+0

Il problema che ho riscontrato è che se provavo a usare la parola chiave async e rendevo il metodo async, il metodo lanciava "Un modulo o un handler asincrono completato mentre un'operazione asincrona era ancora in sospeso." – Tom

1

Se MUST convertito asincrono di sincronizzare.

public User GetCurrentUserSynch() 
    { 
     return Task.Run(() => 
     { 
      var asyncResult = entityStorage.GetCurrentUser(); 
      while (!asyncResult.IsCompleted) 
      { 
       Application.Current.TryFindResource(new object()); // This is for WPF but you can do some other nonsense action of your choosing 
      } 

      return asyncResult.Result; 
     }).Result; 
    } 

In caso contrario, utilizzare la risposta di Stephen.

Problemi correlati