web-dev-qa-db-fra.com

Est-il possible d'appeler une méthode attendue dans une méthode non asynchrone?

Dans une application Windows 8 en C #/XAML, je souhaite parfois appeler une méthode attendue à partir d'une méthode non asynchrone.

En fait, est-il correct de remplacer ceci:

  public async Task<string> MyCallingMethod()
  {
      string result = await myMethodAsync();
      return result;
  }

par ça :

   public string MyCallingMethod()
   {
       Task.Run(async () => {
            string result = await myMethodAsync();
            return result;
             });
   }

L'avantage pour moi est que je peux utiliser MyCallingMethod sans attendre mais est-ce correct? Cela peut être un avantage si je veux passer un paramètre ref pour MyCallingMethod car il n'est pas possible d'avoir des paramètres ref dans une méthode async.

29
Thomas Salandre

Dans la méthode non asynchrone, vous pouvez soit démarrer la tâche de manière asynchrone et ne pas attendre le résultat:

public void MyCallingMethod()
{
    Task t = myMethodAsync();
}

ou vous pouvez attacher le gestionnaire d'événements ContinueWith, qui est appelé après avoir terminé la tâche,

public void MyCallingMethod()
{
    myMethodAsync().ContinueWith(
        result =>
        {
            // do stuff with the result
        });
}

ou vous pouvez obtenir le résultat de la tâche de manière synchrone:

public string MyCallingMethod()
{
    string result = myMethodAsync().Result;
    return result;
}
50
Martin Suchan

Vous ne devriez vraiment pas essayer de faire quelque chose comme ça si vous êtes sur le thread d'interface utilisateur, car cela signifie que vous bloquerez le thread. Vous devez plutôt contourner le paramètre ref, par exemple en acceptant un paramètre d'un type de classe simple, qui contient la valeur que vous souhaitez modifier.

Une autre raison pour ne pas le faire est qu'il ne vous permettra toujours pas d'utiliser les paramètres ref, car lambdas ne peut pas accéder aux paramètres ref de la méthode englobante.

Mais si vous voulez vraiment faire cela (encore une fois, je pense vraiment que vous ne devriez pas), alors vous devrez obtenir le résultat de Task. Quelque chose comme:

public string MyCallingMethod()
{
    var task = Task.Run(async () =>
    {
        return await myMethodAsync();
    });
    return task.Result;
}
19
svick