Ho un multi-tier .Net 4.5 applicazione che si chiama un metodo che utilizza C # 's nuova async
e await
parole chiave che solo si blocca e non riesco a capire perché.
In fondo ho un metodo asincrono che estende la nostra utilità di database OurDBConn
(fondamentalmente un wrapper per il sottostante DBConnection
e gli DBCommand
oggetti):
public static async Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
string connectionString = dataSource.ConnectionString;
// Start the SQL and pass back to the caller until finished
T result = await Task.Run(
() =>
{
// Copy the SQL connection so that we don't get two commands running at the same time on the same open connection
using (var ds = new OurDBConn(connectionString))
{
return function(ds);
}
});
return result;
}
Quindi ho un metodo asincrono di medio livello che lo chiama per ottenere alcuni totali a esecuzione lenta:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Finalmente ho un metodo UI (un'azione MVC) che viene eseguito in modo sincrono:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
Il problema è che rimane per sempre su quest'ultima riga. Fa la stessa cosa se chiamo asyncTask.Wait()
. Se eseguo direttamente il metodo SQL lento, ci vogliono circa 4 secondi.
Il comportamento che mi aspetto è che quando arriva a asyncTask.Result
, se non è finito, dovrebbe aspettare finché non lo è, e una volta che è dovrebbe restituire il risultato.
Se passo con un debugger, l'istruzione SQL viene completata e la funzione lambda termina, ma la return result;
riga di GetTotalAsync
non viene mai raggiunta.
Hai idea di cosa sto sbagliando?
Qualche suggerimento su dove devo indagare per risolvere questo problema?
Potrebbe essere un punto morto da qualche parte e, in tal caso, esiste un modo diretto per trovarlo?
SynchronizationContext
.