J'ai une application .Net 4.5 multiniveau appelant une méthode utilisant le nouveau C # async
await
mots-clés de et qui se bloque juste et je ne vois pas pourquoi.
En bas, j'ai une méthode asynchrone qui étend notre utilitaire de base de données OurDBConn
(essentiellement un wrapper pour le sous DBConnection
- jacent et les DBCommand
objets):
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;
}
Ensuite, j'ai une méthode asynchrone de niveau intermédiaire qui appelle ceci pour obtenir des totaux lents:
public static async Task<ResultClass> GetTotalAsync( ... )
{
var result = await this.DBConnection.ExecuteAsync<ResultClass>(
ds => ds.Execute("select slow running data into result"));
return result;
}
Enfin, j'ai une méthode d'interface utilisateur (une action MVC) qui s'exécute de manière synchrone:
Task<ResultClass> asyncTask = midLevelClass.GetTotalAsync(...);
// do other stuff that takes a few seconds
ResultClass slowTotal = asyncTask.Result;
Le problème est qu'il reste à jamais sur cette dernière ligne. Ça fait la même chose si j'appelle asyncTask.Wait()
. Si j'exécute directement la méthode SQL lente, cela prend environ 4 secondes.
Le comportement auquel je m'attends est que lorsque cela arrive asyncTask.Result
, si ce n'est pas fini, il doit attendre jusqu'à ce que ce soit le cas, et une fois qu'il est, il doit renvoyer le résultat.
Si je passe avec un débogueur, l'instruction SQL se termine et la fonction lambda se termine, mais le return result;
ligne de GetTotalAsync
n'est jamais atteinte.
Une idée de ce que je fais mal?
Avez-vous des suggestions sur les domaines où je dois enquêter pour résoudre ce problème?
Cela pourrait-il être une impasse quelque part, et si oui, y a-t-il un moyen direct de le trouver?
SynchronizationContext
.