在C#类中有多个定时器可以有一个异常处理程序吗? [英] Is it possible to have one Exception handler for multiple timers in a C# class?

查看:224
本文介绍了在C#类中有多个定时器可以有一个异常处理程序吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



不幸的是程序运行的计算机之一是具有程序崩溃电脑很难得到,而且不能加载调试软件(它是一个外部的嵌入式PC,没有网络访问)。



我已经尝试找到原因然而,崩溃(例如未处理的exeption)没有找到任何东西,并且没有访问PC,因为它在远程位置。



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



我的代码是:

  //未处理的异常处理的当前域
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();

抛出新异常(ABC);

}

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

私有字符串SetLabel(Exception ex)
{
String str;

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

return str;
}

private void ChangeFilesTimer_Tick(object sender,EventArgs e)
{
RunChangeFiles();
抛出新异常(2);
}

为什么不抛出新的异常调用未处理的异常错误?
如何使用AppDomain获取未处理的异常处理程序来处理RunChangeFiles中的此异常/异常?



AppDomain上的代码基于 MSDN示例

解决方案

如果你的计时器是一个 System.Timers.Timer 通过MSDN 此处


Timer组件捕获并禁止事件处理程序为Elapsed事件抛出的所有异常。


看看这个类似的问题:
如何获取在Timer 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()之前订阅此活动。






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

  try 
{
/// ...
}
catch例外ex)
{
if(ex为ArgumentException)
{
///处理已知或特定的异常
}
else
{
/// log然后重新抛出未处理的异常
logExceptions(ex);
throw;
}
}


I have a C# program which runs a system tray application - transferring / moving / creating / editing files in the background.

There is alot of exception handling and loop handling to prevent the program from crashing / getting stuck if the user manual deletes a file the program is working with.

Unfortunately one of the computer the program is running on is having the program crash. The computer is very hard to get, and cannot have debugging software loaded on (it is an embedded PC outside with no network access).

I have tried finding the cause of the crash (such as an unhandled exeption) however have not found anything and do not have access to the PC as it is in a remote location.

I was hoping to find a way to use AppDomain / an UnhandledExceptionEventHandler to catch all unhandled exceptions and log them for diagnosis. However the exception I have (deliberately) created in the office inside the class "DoSomething.class", are crashing the WinForm application rather than logging the exception error.

My code is:

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

Why doesn't the throw new exception call the unhandled exception error? How would I use AppDomain to get the unhandled exception handler to handle this exception / exceptions in the RunChangeFiles?

Code on AppDomain is based of MSDN examples

解决方案

If your timer is a System.Timers.Timer the reason is documented by MSDN here:

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

Take a look at this similar question: How do I get the Exception that happens in Timer Elapsed event?

You'll have to catch the exceptions that are thrown in the elapsed handler, and rethrow them on a ThreadPool thread.

Using your code above and extending the answer from the referenced question:

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


If your timer is a System.Windows.Forms.Timer then you will need to hook into the Application.ThreadException event to handle unhandled exceptions.

Subscribe to this event prior to calling Application.Run().


You can also handle logging of the Exception in a local exception handling block before rethrowing the 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;  
    }
}

这篇关于在C#类中有多个定时器可以有一个异常处理程序吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆