0

From the Microsoft documentation the System.Timers.Timer elapsed method should swallow all exceptions.

The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event.

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

However when subscribing using an async void method an exception is produced which crashes the application. See the below code:

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")); } } 

The lines commented A and B do not crash the application. The line commented C does.

Why is this the case?

3
  • 3
    Yuck, you are making it sound as though it is a good feature. It ranks high amongst the worst .NET 1.0 decisions. And sure, doesn't work, the code that fires the event is long gone by the time that Task completes. So it can't catch anything. An async-void method is fire-and-forget code. Commented Sep 12, 2017 at 12:38
  • I agree, they all should throw. But I was surprised when the await async one did. Commented Sep 12, 2017 at 13:30
  • async void exceptions cannot be caught by normal means. Commented Sep 15, 2017 at 16:42

1 Answer 1

4

The link you provided states:

The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework. Note, however, that this is not true of event handlers that execute asynchronously and include the await operator (in C#) or the Await operator (in Visual Basic). Exceptions thrown in these event handlers are propagated back to the calling thread, as the following example illustrates. For more information on exceptions thrown in asynchronous methods, see Exception Handling (Task Parallel Library).

Since you are using await then the latter part of the documentation applies:

Exceptions thrown in these event handlers are propagated back to the calling thread, as the following example illustrates.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.