web-dev-qa-db-fra.com

Meilleure façon de convertir la méthode asynchrone basée sur le rappel en tâche attendue

Quelle serait la meilleure façon de convertir/encapsuler une méthode asynchrone "classique" qui utilise un rappel vers quelque chose qui renvoie une tâche (attendue)?

Par exemple, étant donné la méthode suivante:

public void GetStringFromUrl(string url, Action<string> onCompleted);

La seule façon que je sache d'envelopper dans une méthode renvoyant une tâche est:

public Task<string> GetStringFromUrl(string url)
{
     var t = new TaskCompletionSource<string>();

     GetStringFromUrl(url, s => t.TrySetResult(s));

     return t.Task;
}

Est-ce le seul moyen d'y parvenir?

Et existe-t-il un moyen d'envelopper l'appel à GetStringFromUrl (url, rappel) dans la tâche elle-même (c'est-à-dire que l'appel lui-même s'exécuterait à l'intérieur de la tâche plutôt que de manière synchrone)

63
Philippe Leybaert

Votre code est court, lisible et efficace, donc je ne comprends pas pourquoi cherchez-vous des alternatives, mais je ne pense à rien. Je pense que votre approche est raisonnable.

Je ne sais pas non plus pourquoi pensez-vous que la partie synchrone est correcte dans la version originale, mais vous voulez l'éviter dans celle basée sur Task. Si vous pensez que la partie synchrone peut prendre trop de temps, corrigez-la pour les deux versions de la méthode.

Mais si vous souhaitez l'exécuter de manière asynchrone (c'est-à-dire sur la ThreadPool) uniquement dans la version Task, vous pouvez utiliser Task.Run() :

public Task<string> GetStringFromUrl(string url)
{
    return Task.Run(() =>
    {
        var t = new TaskCompletionSource<string>();

        GetStringFromUrl(url, s => t.TrySetResult(s));

        return t.Task;
    });
}
32
svick

Votre implémentation supposée est parfaitement adaptée à cela, en supposant que le rappel ne gère que les situations réussies. Que se passe-t-il actuellement si une exception se produit dans les fondements asynchrones de l'implémentation GetStringFromUrl? Il n'y a aucun moyen réel pour eux de propager cela dans le rappel Action ... est-ce qu'ils l'avalent simplement et vous retournent nul ou quelque chose?

La seule chose que je recommanderais est d'utiliser la nouvelle convention de dénomination des méthodes asynchrones avec le suffixe XXXAsync.

3
Drew Marsh