Sobes.tech
Middle+

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 :

  1. Utilisation de la propriété Result ou de la méthode Wait() sur un objet Task.

    // 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;
    }
    
  2. 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() et Result bloquent 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ès await, 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;