从Microsoft文档中,System.Timers.Timer
已用过的方法应该吞下所有异常。
Timer组件捕获并抑制事件处理程序为Elapsed事件抛出的所有异常。
https://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
但是,当使用async void
方法进行订阅时,会产生一个导致应用程序崩溃的异常。请参阅以下代码:
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"));
}
}
评论A和B的行不会使应用程序崩溃。该行评论C确实。
为什么会这样?
答案 0 :(得分:3)
Timer组件捕获并抑制所引发的所有异常 Elapsed事件的事件处理程序。此行为受制于 在.NET Framework的未来版本中进行更改。但请注意 对于异步执行的事件处理程序而言,情况并非如此 包括await运算符(在C#中)或Await运算符(在Visual中 基本)。这些事件处理程序中抛出的异常会被传播回来 调用线程,如下例所示。更多 有关异步方法中抛出的异常的信息,请参阅 异常处理(任务并行库)。
由于您使用的是await
,因此文档的后半部分适用:
这些事件处理程序中抛出的异常会被传播回来 调用线程,如下例所示。