Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global Error Handling in Task.Run

I have a wpf c# app.

I normally use a global error handler to catch all errors:

private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
    try
    {
        Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => Xceed.Wpf.Toolkit.MessageBox.Show(e.Exception.ToString(), "Error",
          MessageBoxButton.OK, MessageBoxImage.Error)));
        e.Handled = true;
        InformedWorkerDataService.Common.Shared.RecordMessage(e.Exception.ToString(), true);
    }
    finally { }
}

However, if start off a task.run 'bit of code' and it throws an error then i have observed that error is not caught:

Task.Run(() =>
{
    throw and error here    
});

so I have to put a 'Try-Catch' thing in to capture it:

Task.Run(() =>
{
    try
    {
        throw an error here
    }
    catch (Exception ex)
    {
        do  something with error
    }
});

~ which defeats the object of having a Global Error handler

What should I do?

like image 210
Andrew Simpson Avatar asked Oct 27 '25 14:10

Andrew Simpson


2 Answers

There is an TaskScheduler.UnobservedTaskException event that you can use

TaskScheduler.UnobservedTaskException += (s, e) => {
    e.Exception  //The Exception that went unobserved.
    e.SetObserved(); //Marks the Exception as "observed," thus preventing it from triggering exception escalation policy which, by default, terminates the process.
};

Occurs when a faulted task's unobserved exception is about to trigger exception escalation policy, which, by default, would terminate the process.

This application domain-wide event provides a mechanism to prevent exception escalation policy (which, by default, terminates the process) from triggering

like image 89
dkozl Avatar answered Oct 30 '25 04:10

dkozl


As mentioned in my comment to the accepted answer, the TaskScheduler.UnobservedTaskException is not guarenteed to fire in real time with the exception being thrown. This means that using this handler for user notification can be quite confusing as the user action and error notification will not happen synchronously. For user driven handling of 'unexpected' task exceptions, you could create helper methods as below and use TaskEx.Run instead of Task.Run:

public static class TaskEx
{
    public static Task Run(Action function)
    {
        return Task.Run(() =>
        {
            try
            {
                function();
            }
            catch (Exception ex)
            {
                TraceEx.TraceException(ex);
                //Dispatch your MessageBox etc.
            }
        });
    }
}
like image 32
Andrew Hanlon Avatar answered Oct 30 '25 03:10

Andrew Hanlon