Peut-on appeler du code asynchrone de manière synchrone?
sobes.tech IA
Réponse de l'IA
Oui, c'est possible, mais cela peut entraîner des problèmes, notamment des blocages.
Méthodes d'appel synchrone de code asynchrone :
-
Utilisation de la propriété
Resultou de la méthodeWait()sur un objetTask.// Appel synchrone d'une méthode asynchrone Task.Run(async () => await SomeAsyncTask()).Wait(); // Récupération du résultat d'une méthode asynchrone de manière synchrone var result = SomeAsyncTaskWithResult().Result;async Task SomeAsyncTask() { await Task.Delay(100); } async Task<int> SomeAsyncTaskWithResult() { await Task.Delay(100); return 42; } -
Utilisation de
GetAwaiter().GetResult():// Appel synchrone d'une méthode asynchrone avec récupération du résultat var result = SomeAsyncTaskWithResult().GetAwaiter().GetResult();
Inconvénients de cette approche :
- Blocages : Le problème le plus courant, surtout dans les threads d'interface utilisateur ou dans les contextes ASP.NET avec un contexte de synchronisation.
Wait()etResultbloquent le thread actuel en attendant la fin de la tâche. Si la méthode asynchrone tente de capturer le contexte de synchronisation bloqué pour continuer aprèsawait, cela entraîne un blocage. - Réduction des performances et de la scalabilité : Bloquer des threads au lieu d'utiliser des opérations asynchrones consomme plus de ressources et réduit la capacité de l'application à traiter plusieurs requêtes simultanément (par exemple, dans des applications web).
- Comportement peu évident : Mélanger code asynchrone et synchrone peut rendre le flux d'exécution difficile à comprendre et à déboguer.
Dans la plupart des cas, la bonne pratique consiste à utiliser await pour continuer l'exécution asynchrone ou, si l'exécution du code asynchrone doit se faire au point d'entrée de l'application (par exemple, Main), utiliser Task.Run() avec Wait() ou rendre Main asynchrone, si la version de C# le supporte (async Task Main).
Exemple d'appel sécurisé à du code asynchrone depuis une méthode synchrone, en utilisant Task.Run pour déplacer l'exécution dans le pool de threads :
// Appel sécurisé à une méthode asynchrone depuis un contexte synchrone
Task.Run(async () =>
{
await SomeAsyncTask();
}).Wait();
// Appel sécurisé à une méthode asynchrone avec résultat
var result = Task.Run(async () =>
{
return await SomeAsyncTaskWithResult();
}).Result;