繁体   English   中英

框架中的事件异常处理

[英]Event Exception Handling In Framework

我正在寻找有关处理事件异常的最佳实践的一些指导。 当前,当我的应用程序中引发异常时,该异常消息会显示在弹出对话框中,然后单击确定后,应用程序将重新启动。 我看到的问题是,某些第三方库的事件处理程序中发生了许多异常,并且这些异常被吞噬且从未显示,因为它们位于后台线程中。 这里有一些人们已经想到的解决方案,我想知道其中的任何一种都是最好的方法。

  1. 将后台线程转发到应用程序中每个事件处理程序中的UI线程。
  2. 将事件包装在另一个类中,该类在调用该事件的每个方法周围具有try / catch。 然后,如果发生异常,则catch会将异常转发到UI线程。
  3. 获得对第三方库的访问权限,并在调用事件的位置进行尝试/捕获,然后可以通过全局事件将其转发到主应用程序。

让我们以列出方式来讨论您的选择:

1)将后台线程转发到应用程序中每个事件处理程序中的UI线程。

你不应该,你不能! 因为:

  • 您不能假装该事件“可能来自第三方”启动了另一个后台线程或计时器。
  • 拥有后台线程的全部目的不是冻结UI,然后您将通过冗长的执行代码使用户界面陷入困境。

2)将事件包装在另一个类中,该类具有对调用该事件的每个方法的尝试/捕获。 然后,如果发生异常,则catch会将异常转发到UI线程。

  • 与上一点相同。 您不能假装该事件会启动另一个线程。

3)可以访问第三方库,并在调用事件的位置进行尝试/捕获,然后可以通过全局事件将其转发到主应用程序。

实际上,这是一个错误的选择, 即使可以 ,您也不应更改第三方库的代码。 因为:

  • 您不是这些库的作者。
  • 每当您要更新库版本甚至更改库时,都必须在此处重写代码。

那你该怎么办? 答案是您当前正在做的事情:
每当引发任何异常时,记录该异常都会重新启动您的过程,然后在过程中的某个时刻将记录的错误发送到您的电子邮件中,然后开始修复它们。

以上都不是。 而是将ApplicationAppDomain上的事件挂钩以获取未处理的异常。

进一步的信息: WPF应用Application.DispatcherUnhandledException的全局异常处理事件Application.DispatcherUnhandledException仅针对在主UI线程上引发的异常触发。 但是, AppDomain.CurrentDomain.UnhandledException应该在任何线程中的任何未处理的异常上触发(不幸的是,无法阻止应用程序在到达此处后关闭)。

对最佳做法进行了一些快速研究,发现建议您使用try\\catch块手动处理后台线程上的异常。 阅读本页http://www.albahari.com/threading/上的异常部分,并查看此StackOverflow问题: 在单独的线程上捕获未处理的异常

如果钩住AppDomain.UnhandledException事件,那么问题就不在于它们可能在后台线程上回调,而是第三方库明确吞下了处理程序引发的异常。 这是一个表现不佳的库,但是,由于您正在编写事件处理程序代码,因此可以在事件处理程序中捕获异常并强制应用程序关闭。

由于不能通过引发异常来停止第三方库,因此可以通过调用以下命令来强制终止线程:

Thread.CurrentThread.Abort();

Thread.Abort()通常被认为是一种不好的做法,但是在这里它的危险性要小一些,因为您正在中止自己,因此不会将异常注入到可能令人讨厌的位置(您也知道线程不在非托管上下文中) ,因此它会立即中止。)这仍然是一个令人讨厌的骇客,但是第三方应用程序却没有给您太多选择。 ThreadAbortException不能被“停止”,因此第三方代码将在其异常处理程序结束时终止其线程(即使他们试图吞没它)。 如果第三方库确实很讨厌,它可能会在其catch或finally块中调用许多代码,甚至使用肮脏的技巧像启动其他线程一样保持活动,但这样做必须非常恶意。

为了获得友好的错误消息行为,您可以使用SynchronizationContext或Dispatcher将Exception编组到UI线程,以调用异常处理程序显示(最简单的方法可能是重新抛出该异常;我建议将其嵌入为InnerException。这样您就不会丢失堆栈跟踪。)

如果您真的不信任该库(并且即使通过捕获并最终阻止也不希望给予它生存的机会),则可以使用阻止调用显式地编组到UI线程(以友好的方式显示错误消息)方式),然后调用Environment.FailFast()杀死您的进程。 这是终止的一种特别苛刻的方式(它不会调用任何清除代码,并且从字面上尽可能快地删除该过程),但是,如果应用程序状态已非常损坏,则它可以最大程度地减少产生任何潜在破坏性副作用的可能性。 这里需要注意的一件事是,UI线程可能会被绑定到第三方代码的某些其他UI调用阻止。 如果发生这种情况,应用程序将死锁。 同样,这将是非常恶意的事情,因此您可能会忽略它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM