2017-09-12 3 views
0

Dans la documentation Microsoft, la méthode écoulée System.Timers.Timer doit englober toutes les exceptions.System.Timers.Timer se bloque lors de l'affichage de l'exception

Le composant Timer intercepte et supprime toutes les exceptions levées par les gestionnaires d'événements pour l'événement Elapsed.

https://msdn.microsoft.com/en-us/library/system.timers.timer.aspx

Cependant lors de la souscription au moyen d'un procédé async void une exception est produit qui bloque l'application. Voir le code ci-dessous:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Timer timer = new Timer(100); 
     //timer.Elapsed += On_ElapsedSync; //A 
     //timer.Elapsed += On_ElapsedAsync; //B 
     timer.Elapsed += On_ElapsedAsyncVoid; //C 
     timer.Start(); 

     Console.WriteLine("Running..."); 
     Console.ReadLine(); 
    } 

    private static void On_ElapsedSync(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Throwing..."); 
     throw new Exception("My Exception"); 
    } 

    private static void On_ElapsedAsync(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Throwing..."); 
     Task.Run(() => throw new Exception("Async Exception")); 
    } 

    private static async void On_ElapsedAsyncVoid(object sender, ElapsedEventArgs e) 
    { 
     Console.WriteLine("Throwing..."); 
     await Task.Run(() => throw new Exception("Async Exception")); 
    } 
} 

Les lignes commentées A et B ne plantent pas l'application. La ligne a commenté C fait.

Pourquoi est-ce le cas?

+2

Yuck, vous donnez l'impression que c'est une bonne fonctionnalité. Il se classe parmi les pires décisions .NET 1.0. Et bien sûr, cela ne fonctionne pas, le code qui déclenche l'événement est révolu depuis le début de la tâche. Donc, il ne peut rien attraper. Une méthode async-void est du code fire-and-forget. –

+0

Je suis d'accord, ils devraient tous jeter. Mais j'ai été surpris quand l'attente asynchrone l'a fait. –

+0

Les exceptions ['async void' ne peuvent pas être interceptées par des moyens normaux] (https://msdn.microsoft.com/fr-fr/magazine/jj991977.aspx). –

Répondre

3

The link you provided états:

Les prises de composants de la minuterie et supprime toutes les exceptions lancées par gestionnaires d'événements pour l'événement échues. Ce comportement est soumis à la modification dans les versions ultérieures de .NET Framework. Notez cependant que cela n'est pas vrai pour les gestionnaires d'événements qui s'exécutent de manière asynchrone et incluent l'opérateur wait (en C#) ou l'opérateur Await (en Visual Basic). Les exceptions levées dans ces gestionnaires d'événements sont renvoyées au thread appelant, comme l'illustre l'exemple suivant. Pour plus d'informations sur les exceptions levées dans les méthodes asynchrones, voir Gestion des exceptions (bibliothèque parallèle des tâches).

Puisque vous utilisez await alors la dernière partie de la documentation s'applique:

exceptions lancées dans ces gestionnaires d'événements sont propagées retour au thread appelant, comme l'exemple ci-dessous illustre.