Is it possible to have one Exception handler for m

2019-05-26 22:39发布

问题:

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

回答1:

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