Task.Run 中的全局错误处理用于实时用户通知
Global Error Handling in Task.Run for realtime User ntofication
我有一个 wpf c# 应用程序。
我通常使用全局错误处理程序来捕获所有错误:
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 { }
}
但是,如果从 task.run 'bit of code' 开始并抛出错误,那么我观察到该错误未被捕获:
Task.Run(() =>
{
throw and error here
});
所以我必须放入一个 'Try-Catch' 东西来捕获它:
Task.Run(() =>
{
try
{
throw an error here
}
catch (Exception ex)
{
do something with error
}
});
~ 这破坏了拥有全局错误处理程序的对象
但是,如果我使用这种方法:
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.
};
...它将执行我的全局异常处理,但如果我想实时通知用户错误,它就不会做得很好,因为它在一个单独的线程上。
什么是好的折衷方案?
不幸的是,TaskScheduler.UnobservedTaskException
不能保证在抛出异常的情况下实时触发。这意味着使用此处理程序进行用户通知可能会非常混乱,因为用户操作和错误通知不会同步发生。对于 'unexpected' 任务异常的用户驱动处理,您可以创建如下辅助方法并使用 TaskEx.Run
而不是 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.
}
});
}
}
显然,这不像添加全局处理程序那么简单(出于跟踪目的仍应这样做)但足够简单,可以在 UI 驱动代码中实现。
我有一个 wpf c# 应用程序。
我通常使用全局错误处理程序来捕获所有错误:
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 { }
}
但是,如果从 task.run 'bit of code' 开始并抛出错误,那么我观察到该错误未被捕获:
Task.Run(() =>
{
throw and error here
});
所以我必须放入一个 'Try-Catch' 东西来捕获它:
Task.Run(() =>
{
try
{
throw an error here
}
catch (Exception ex)
{
do something with error
}
});
~ 这破坏了拥有全局错误处理程序的对象 但是,如果我使用这种方法:
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.
};
...它将执行我的全局异常处理,但如果我想实时通知用户错误,它就不会做得很好,因为它在一个单独的线程上。
什么是好的折衷方案?
不幸的是,TaskScheduler.UnobservedTaskException
不能保证在抛出异常的情况下实时触发。这意味着使用此处理程序进行用户通知可能会非常混乱,因为用户操作和错误通知不会同步发生。对于 'unexpected' 任务异常的用户驱动处理,您可以创建如下辅助方法并使用 TaskEx.Run
而不是 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.
}
});
}
}
显然,这不像添加全局处理程序那么简单(出于跟踪目的仍应这样做)但足够简单,可以在 UI 驱动代码中实现。