Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Task, qui es-tu ? partie 8

Task<T> est utilisé dans le cas où une tâche retourne un résultat. Il y a plusieurs façons de récupérer ce dernier mais toutes ne se valent pas…

Liens rapides vers la série complète

Task et Task<T>

Récupérer les informations retournée par une Task<T> est un passage obligé, soit parce que cela coule de source (demander un résultat et ne pas en ternir compte c’est écrire du code qui peut être mis en commentaire !), soit parce qu’il faut au minimum s’assurer que tout s’est bien passé ou traiter les éventuelles erreurs. Et dans ce cas on entend ici par “résultat” tous ces différents types de résultat (une exception lue via la propriété Exception est un résultat comme un autre).

Result

Cette propriété est du type passé à l’appel de la tâche et n’existe bien entendu que dans le cas de Task<T>.

De la même façon que Wait, lire Result va bloquer de façon synchrone le thread appelant jusqu’à temps que la tâche soit complétée. Ce n’est donc pas une bonne idée que de procéder de la sorte car comme pour Wait les deadlocks ne sont pas loin !

De plus si des erreurs se produisent pendant l’accès à Result elles seront agrégées dans une AggregateException ce qui en compliquera le traitement.

Exception

Comme son nom le laisse supposer cette propriété retourne les exceptions de la tâche sous une forme agrégée. A la différence de Result et Wait la lecture de cette propriété n’est pas bloquante. Elle retourne null en permanence sauf si la tâche est terminée et qu’elle a généré des erreurs. Cette propriété se retrouve aussi bien dans Task que Task<T> bien entendu.

GetAwaiter().GetResult()

Le membre GetAwaiter a été ajouté dans Task dans .NET 4.5 uniquement pour les besoins de await mais en théorie rien n’interdit de s’en servir directement. Il n’y a que peu de différence avec Result mais elle peut avoir son importance : les exceptions ne seront pas agrégées ce qui peut être plus pratique à traiter.

await

Ce n’est bien entendu pas un membre de Task mais comme il est question des résultats retournés par une tâches il semble essentiel de rappeler que await attendra de façon asynchrone un résultat en provenance de Task (ou Task<T>) et qu’il est donc non bloquant. Dans tous les cas sauf contrainte spécifique qui resterait à définir et justifier un résultat de Task s’obtient par await. C’est de loin la méthode la plus efficace. Elle est préférable à toutes les autres, que cela soit Wait, Result, Exception or GetAwaiter. 

Conclusion

Finalement l’utilisation de Task c’est facile, il ne faut pratiquement rien utiliser sauf un await sur la tâche… On ne créée pas d’instances, on await juste les données.

Il est clair qu’on est parti de loin et il y a encore pas longtemps il fallait faire de drôles de détours réservés à des spécialistes pour un code difficile à lire et à maintenir. Avec les dernières versions du Framework, Parallel, la TPL, async/await et Task, tirer partie des multicoeurs est devenu un jeu d’enfant…

Mais ce n’est pas fini, puisque dans la prochaine partie nous parlerons justement des continuations !

Stay Tuned !

blog comments powered by Disqus