Gestion des exceptions des méthodes asynchrones dans une #Windows (#Phone) App
Le mot clef async et son utilisation est vraiment fantastique dans une application C# 5.0 car il facilite vraiment l’écriture de traitement asynchrones. J’aimerais dans ce post rappeller le comportement d’une application Windows (Phone) Store lorsqu’une exception se produit dans une méthode “async”.
Plusieurs scénarii sont possibles lorsqu’une exception est levée dans une méthode async et cela dépend de la signature de la méthode.
La méthode ne retourne rien (void)
Dans une application Windows 8.0, votre application crashera… autant dire que c’est une très mauvaise pratique et qu’il faut toujours retourner une Task ! Comment faire dans le cas alors où vous devez respecter une signature de méthode bien précise (event handler, obligation de fournir une Action, etc.) ? Mon astuce consiste à créer une méthode intermédiaire. Attention cependant que le traitement sera asynchrone alors que le composant qui nécessite une action s’attends à quelque chose de synchrone.
public MaPage() { Loaded += PageWenContent_Loaded; } void PageWenContent_Loaded(object sender, RoutedEventArgs e) { //Attention, appeler cette méthode n’est pas bloquant ( pas d'await) MonTraitementAsync(); } //Bonne signature private async Task MonTraitementAsync() { }
Il reste sinon la possibilité d’utiliser Try/Catch pour bloquer les éventuelles exceptions.
Dans une application Windows 8.1, vous pouvez récupérer l’exception dans l’handler général des erreurs de votre application: Application.Current.UnhandledException. Dans cet handler vous pouvez éventuellement la marquer comme handled pour empêcher l’application de crasher. Attention cependant, cela aura aussi comme effet de perdre le rapport de crash sur le Store.
Application.Current.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => { //No, no crash no man e.Handled = true; };
La méthode retourne une Task
Dans ce cas l’exception est stockée dans l’objet Task retourné par la méthode. Si vous l’utilisez (en utilisant await ou utilisation directe) vous pouvez lire l’exception et la traiter.
Si vous ne faites rien de la Task (Fire and Forget) alors il vous reste un moyen de détecter l’exception : vous abonner à l’événement TaskScheduler.UnobservedTaskException. Attention cependant, cet événénement ne sera pas levé en temps réél mais au moment où la Task initiale est collectée par le Garbage Collector.
En éspérant que cela vous sera utile !
Commentaires