Comment appeler une méthode asynchrone depuis une méthode synchrone en C# ?
La programmation asynchrone se “propage” à travers la base de code. Elle a été comparée à un virus zombie. La meilleure solution est de la laisser se propager, mais parfois ce n’est pas possible.
J’ai écrit quelques types dans ma bibliothèque Nito.AsyncEx pour gérer une base de code partiellement asynchrone. Il n’existe aucune solution qui fonctionne dans toutes les situations, cependant.
Solution A
Si vous avez une méthode asynchrone simple qui n’a pas besoin de se synchroniser avec son contexte, vous pouvez utiliser Task.WaitAndUnwrapException :
var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();
Vous ne voulez pas utiliser Task.Wait ou Task.Result car ils encapsulent les exceptions dans une AggregateException.
Cette solution n’est appropriée que si MyAsyncMethod ne se synchronise pas avec son contexte. En d’autres termes, chaque await dans MyAsyncMethod devrait se terminer par ConfigureAwait(false). Cela signifie qu’elle ne peut pas mettre à jour des éléments d’interface utilisateur ni accéder au contexte de requête ASP.NET.
Solution B
Si MyAsyncMethod a besoin de se synchroniser avec son contexte, vous pouvez peut-être utiliser AsyncContext.RunTask pour fournir un contexte imbriqué :
var result = AsyncContext.RunTask(MyAsyncMethod).Result;
*Mise à jour 14/04/2014 : Dans les versions plus récentes de la bibliothèque, l’API est la suivante :
var result = AsyncContext.Run(MyAsyncMethod);
(Il est correct d’utiliser Task.Result dans cet exemple car RunTask propagera les exceptions de Task).
La raison pour laquelle vous pourriez avoir besoin de AsyncContext.RunTask au lieu de Task.WaitAndUnwrapException est une possibilité de deadlock assez subtile qui se produit sur WinForms/WPF/SL/ASP.NET :
-
Une méthode synchrone appelle une méthode asynchrone, obtenant une
Task. -
La méthode synchrone effectue une attente bloquante sur la
Task. -
La méthode
asyncutiliseawaitsansConfigureAwait. -
La
Taskne peut pas se term
(Réponse tronquée)