views:

52

answers:

2

I'm working with Windows Forms application and hava a manager class that uses System.Timers.Timer to periodly check data from database.

How do I get the Exception that occurs in timer Elapsed eventhandler delivered into main application? If I'm using the code below, the exception get's "swallowed", and main application never gets it (even if I have handlers for ThreadException and UnHandledException).

// Main Form
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

// Manager class
private System.Timers.Timer _timer;

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            doSomeDatabaseActions();
        }
        catch (Exception ex)
        {
            throw new ApplicationException("How do I get this error back into main thread...", ex);
        }
    }
+3  A: 

Since System.Timers.Timer swallows any exception thrown in the event handler, you will need to marshal the exception to another thread (probably the UI thread). You could do this via Control.Invoke, or by storing error information in a member variable and having the UI thread check this error information after the operation is complete. If non-null, the UI could then throw.

From MSDN:

In the .NET Framework version 2.0 and earlier, the Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework.

Just checked in .NET 4.0, and this behavior has not yet changed.

HTH,
Kent

Kent Boogaart
+2  A: 

You can assign the exception to a local variable and check if an exception has been thrown:

// Main Form
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

// Manager class
private System.Timers.Timer _timer;

    private exception = null;

    void _timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            doSomeDatabaseActions();
        }
        catch (Exception ex)
        {
            this.exception = ex;
        }
    }

    public bool hasExceptionOccured(){
        if(this.exception == null){
            return false;
        }
        return true;
    }

    //The main application will call this to get the exception.
    public Exception getException(){
        return this.exception;
    }
Koekiebox