是否可以在 C# class 中为多个计时器设置一个异常处理程序?

Is it possible to have one Exception handler for multiple timers in a C# class?

我有一个运行系统托盘应用程序的 C# 程序 - 在后台传输/移动/创建/编辑文件。

如果用户手册删除程序正在使用的文件,有很多异常处理和循环处理可以防止程序崩溃/卡住。

不幸的是,运行 所在的其中一台计算机出现程序崩溃。电脑太难搞了,而且不能装调试软件(就是外面的嵌入式PC,没有网络)。

我已尝试找出崩溃的原因(例如未处理的异常),但没有找到任何原因,也无法访问 PC,因为它位于远程位置。

我希望找到一种方法来使用 AppDomain / UnhandledExceptionEventHandler 来捕获所有未处理的异常并将它们记录下来以供诊断。 但是,我在 class "DoSomething.class" 的办公室中(故意)创建的异常正在使 WinForm 应用程序崩溃,而不是记录异常错误。

我的代码是:

    //Current domain for the unhandled exception handling
    AppDomain currentDomain;

    [SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlAppDomain)]
    public MainForm()
    {
        InitializeComponent();

        currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);


        CreateTimer.Interval = Settings.Default.CreateTimer;
        CreateTimer.Start();
        RunCopyProtocol();

        ChangeFilesTimer.Interval = 10000;
        ChangeFilesTimer.Start();
        RunChangeFiles();

        throw new Exception("ABC");

    }

    public void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
    {
        try
        {
            Exception ex = (Exception)args.ExceptionObject;
            SetLabel(ex);
        }
        finally { }
    }

    private string SetLabel(Exception ex)
    {
        String str;

        str = ex.Message;
        Label1.Text = str;

        return str;
    }

    private void ChangeFilesTimer_Tick(object sender, EventArgs e)
    {
        RunChangeFiles();
        throw new Exception("2");
    }

为什么throw new异常不调用unhandled exception错误? 我将如何使用 AppDomain 获取未处理的异常处理程序来处理 RunChangeFiles 中的此异常/异常?

AppDomain 上的代码基于 MSDN examples

如果您的计时器是 System.Timers.Timer MSDN here:

记录了原因

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

看看这个类似的问题: How do I get the Exception that happens in Timer Elapsed event?

您必须捕获在 elapsed 处理程序中抛出的异常,并在 ThreadPool 线程上重新抛出它们。

使用上面的代码并扩展引用问题的答案:

private void ChangeFilesTimer_Tick(object sender, EventArgs e)
{
    try
    {
        RunChangeFiles();
    }
    catch (Exception ex)
    {
        ThreadPool.QueueUserWorkItem(
            _ => { throw new Exception("Exception on timer thread.", ex); });
    }
}

如果您的计时器是 System.Windows.Forms.Timer,那么您将需要挂接到 Application.ThreadException 事件以处理未处理的异常。

在调用 Application.Run() 之前订阅此事件。


您还可以在重新抛出异常之前在本地异常处理块中处理 Exception 的日志记录。

try
{
    /// ...
}
catch (Exception ex)
{
    if (ex is ArgumentException)
    {
        /// handle known or specific exceptions here
    }
    else 
    {
        /// log then rethrow unhandled exceptions here
        logExceptions(ex);
        throw;  
    }
}