百密一疏的Bug很难避免,没有谁能保证,我的程序永远 0 BUG;
突然接手一个很庞大的项目,在项目运行期间会莫名异常结束,异常极难重现,还找不出BUG代码,代码太多了。
这个时候就需要把程序中发生的BUG记录下来,知道哪里BUG了,才好下次更新解决。
把所有代码全部加 try catch ? 那就怀孕了,真的搞大了。
未捕获的异常处理:
一:C# 在 Application 类中提供了 DispatcherUnhandledException 事件,用于处理UI线程上未捕获的异常
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { DispatcherUnhandledException += App_DispatcherUnhandledException; base.OnStartup(e); } void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { //e.Exception 发生的异常 //e.Handled 是否已处理异常事件 } }
但是 DispatcherUnhandledException 捕获不了 非UI线程上发生的异常
二:C# 在 AppDomain 类中提供了 UnhandledException 事件,用于捕获应用程序域中发生的异常
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show("Unhandle"); //MessageBox.Show((e.ExceptionObject == null ? "Null" : e.ExceptionObject.GetType().Name), // "CurrentDomain_UnhandledException:"); }
这样就能捕获应用程序域中发生的异常,当然,包括UI线程和非UI线程异常,如果你有创建应用程序域的需求,创建完成,再绑定下事件即可。
但是AppDomain.UnhandledException 事件没有提供 终止异常,也就是说,异常发生了,你没捕获,这里通知一下,但是该程序结束还得结束。
在这里要特别提到官方封装的 Delegate.BeginInvoke();
"已知:"在异步函数中发生了异常并且没处理:
"求解:"
1.没调用 Delegate.EndInvoke() 函数:
终止执行。 程序不会挂掉,异常丢弃。这是种很隐蔽的BUG,很难发现。
AppDomain.UnhandledException 事件不会通知发生了异常,这里要特别注意。
public void Hello() { World(); Load(); } public void World() {
throw new Exception();
} public void Load() { MessageBox.Show("Suc"); } var action = new Action(Hello); action.BeginInvoke(null, null);
像这种示例,如果在World() 方法中发生了异常,线程会立即终止,Load() 函数就不会执行,程序也不会终止。
一个函数没有执行,也许就会导致很严重的异常,还很难发现。
2.调用了 Delegate.EndInvoke() 函数:
异常抛出, 程序挂掉。
AppDomain.UnhandledException 事件会通知发生了异常
这里也许会有个需求,如果我想处理 AppDomain.UnhandledException 事件中的异常怎么办?程序挂了太恶心了。
我们来继续扩展这个框架
解决在非UI线程中访问UI 异常的小方法
/// <summary> /// 委托 扩展类 /// </summary> public static class DelegateExtension {
/// <summary> /// 可以被捕获异常的异步调用 /// </summary> /// <param name="dele"></param> public static void UnsafeBeginInvoke(this Delegate dele) { var action = new Action(() => { dele.DynamicInvoke(); }); action.BeginInvoke(new AsyncCallback((ar) => { try { action.EndInvoke(ar); } catch (Exception ex) { App.Current.Dispatcher.BeginInvoke(new Action(() => { throw ex; })); } }), null); } }
有点不伦不类哈,厄。把异常推送到UI线程上抛出,让Application.DispatcherUnhandledException 事件处理
其它:C# 在 TaskScheduler 类中提供了 UnobservedTaskException 事件,用于捕获 Task 异步异常
求评论,求吐槽,求求你^v^