System.Timers.Timer在抛出异常时崩溃

时间:2017-09-12 12:31:52

标签: c# timer async-await

从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确实。

为什么会这样?

1 个答案:

答案 0 :(得分:3)

The link you provided州:

  

Timer组件捕获并抑制所引发的所有异常   Elapsed事件的事件处理程序。此行为受制于   在.NET Framework的未来版本中进行更改。但请注意   对于异步执行的事件处理程序而言,情况并非如此   包括await运算符(在C#中)或Await运算符(在Visual中   基本)。这些事件处理程序中抛出的异常会被传播回来   调用线程,如下例所示。更多   有关异步方法中抛出的异常的信息,请参阅   异常处理(任务并行库)。

由于您使用的是await,因此文档的后半部分适用:

  

这些事件处理程序中抛出的异常会被传播回来   调用线程,如下例所示。