4

I have this piece of code, I'm using a timer to call my RunTest() function. If I don't use timer, all the unhandled exception inside RunTest() are caught, but with this timer code they are not getting caught. What mistake am I making?

private static TelemetryClient telemetryClient = new TelemetryClient();

private static System.Timers.Timer aTimer;

    static void Main(string[] args)
    {

        // Register Unhandled Exception Handler
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        // Set the Instrumentation Key to track the WebJob Exception
        TelemetryConfiguration.Active.InstrumentationKey = SecureConfigReader.GetSetting("ApplicationInsightsKey");


        Configure();

        if (args.Length > 0)
        {
            // Create a timer with a ten second interval.
            aTimer = new System.Timers.Timer(10000);
            // Hook up the Elapsed event for the timer.
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            double Scheduled_Interval = Convert.ToDouble(args[0]);
            // Set the Interval to 300 seconds.
            aTimer.Interval = TimeSpan.FromSeconds(Scheduled_Interval).TotalMilliseconds;
            aTimer.Enabled = true;

            Console.WriteLine("Press the Enter key to exit the program.");
            Console.ReadLine();
        }
    }


    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
        RunTests();

    }
    private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        ExceptionTelemetry excTelemetry = new ExceptionTelemetry((Exception)e.ExceptionObject);
        excTelemetry.SeverityLevel = SeverityLevel.Critical;
        excTelemetry.HandledAt = ExceptionHandledAt.Unhandled;
        telemetryClient.InstrumentationKey = SecureConfigReader.GetSetting("ApplicationInsightsKey");
         telemetryClient.TrackException(excTelemetry);
        //make sure all telemetry is sent before closing the app
        telemetryClient.Flush();
    }

    /*
     * 1. Find all tests
     * 2. Run all tests, collecting all results
     * 3. Process alerts if any
     * 4. Save results
     */
    private static void RunTests()
    {

        List<SyntheticTransactionTableEntity> results = new List<SyntheticTransactionTableEntity>();
        List<ISyntheticTransaction> tests = new List<ISyntheticTransaction>();
     }
bansi
  • 55,591
  • 6
  • 41
  • 52

1 Answers1

2

Its documented that:

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

You need to catch within the OnTimedEvent method and then propagate that exception back out e.g by throwing it on another thread if you want CurrentDomain_UnhandledException to catch it (throw in ThreadPool.QueueUserWorkItem())

Alternatively create a handler:

private static void TimerExceptionHandler(Exception ex)
{
    Console.WriteLine(ex.ToString());
    ...
}

Pass it to the ElapsedEventHandler:

aTimer.Elapsed += (sender, e) => { OnTimedEvent(sender, e, TimerExceptionHandler); };

Call it when an exception is thrown:

private static void OnTimedEvent(object source, ElapsedEventArgs e, Action<Exception> timerExceptionHandler)
    try
    {
        RunTests();
    }
    catch (Exception ex)
    {
        timerExceptionHandler(ex);
    }
Alex K.
  • 171,639
  • 30
  • 264
  • 288