框架中的事件异常处理

发布于 2024-11-26 21:02:00 字数 367 浏览 0 评论 0 原文

我正在寻找一些有关处理事件异常的最佳实践的指南。目前,当我的应用程序中引发异常时,异常消息会显示在弹出对话框中,然后应用程序在单击“确定”后重新启动。我看到的问题是,一些第三方库的事件处理程序中发生了很多异常,并且这些异常被吞没并且永远不会显示,因为它们位于后台线程上。以下是不同的人想到的一些解决方案,我想知道其中任何一个都是最好的方法。

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

I'm looking for some guidance on best practices on handling exceptions in events. Currently, when exceptions are thrown in my application, the exception message is displayed in a pop up dialog and then the application restarts after hitting ok. The issue I'm seeing is that a lot of exceptions are occurring in the event handlers of some third party libraries and these exceptions are swallowed and never displayed since they are on a background thread. Here are a few solutions that various people have thought of and I would like to know of any of these are the best approach.

  1. Forward the background thread to the UI thread in every event handler in the application.
  2. Wrap the events in another class which has a try/catch around every method that invokes the event. The catch will then forward the exception to the UI thread if one occurs.
  3. Get access to the third party libraries and put try/catch around where the events are being invoked, which could then be forwarded to the main application by a global event.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦里梦着梦中梦 2024-12-03 21:02:00

让我们按照您列出的方式讨论您的选项:

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

你不应该也不能!因为:

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

2) 将事件包装在另一个类中,该类在调用事件的每个方法周围都有一个 try/catch。如果发生异常,catch 会将异常转发到 UI 线程。

  • 与上一点相同。你不能假装事件启动了另一个线程..

3) 访问第三方库,并在调用事件的地方放置 try/catch,然后可以通过全局事件将其转发到主应用程序。

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

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

那么你必须做什么?答案是您当前正在做的某种事情:
每当抛出任何异常时,记录异常并重新启动您的流程,并在流程中的某个时刻将记录的错误发送到您的电子邮件,然后开始修复它们。

Lets discuss your options the way you listed them:

1) Forward the background thread to the UI thread in every event
handler in the application.

You should not and you can't! because:

  • You can't pretend if that event "which may comes from a third party" starts another background thread
    or timer.
  • The whole point of having background threads is not
    to freeze the UI, you will then struggle the user interface by a long execution codes.

2) Wrap the events in another class which has a try/catch around every method that invokes the event. The catch will then forward the exception to the UI thread if one occurs.

  • The same point as the previous. you can't pretend it that event starts another thread..

3) Get access to the third party libraries and put try/catch around where the events are being invoked, which could then be forwarded to the main application by a global event.

This is a bad choice, really, You should not change that code of third party libraries even if you can. because:

  • You are not the author for those libraries.
  • Whenever you want to update the library version or even change the libraries, you have to rewrite there code..

So what you have to do? The answer is some sort of what you are currently doing:
Whenever any exception thrown, log the exception restart your process, and at some point in your process send the logged bugs to your email and then start fixing them.

冷情妓 2024-12-03 21:02:00

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

更多信息: WPF 应用程序的全局异常处理事件 Application.DispatcherUnhandledException 仅在 ma​​in 上抛出的异常时触发UI 线程。但是,AppDomain.CurrentDomain.UnhandledException 应该在任何线程中的任何未处理异常上触发(不幸的是,无法阻止应用程序在到达此处后关闭)。

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

None of the above. Instead hook up the events on the Application and AppDomain for unhandled exceptions.

Further Information: The global exception handling event for WPF applications Application.DispatcherUnhandledException fires only for exceptions thrown on the main UI thread. However the AppDomain.CurrentDomain.UnhandledException should fire on any unhandled exception in any thread (unfortunately there is no preventing the application from shutting down after ward it reaches here).

Did some quick research on best practices and found that it is recommend that you manually handle exceptions on the background threads with try\catch block. Read the exception part on this page http://www.albahari.com/threading/ and also take a look at this StackOverflow question Catching unhandled exception on separate threads

指尖上的星空 2024-12-03 21:02:00

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

由于第三方库无法通过抛出异常来停止,因此可以通过调用以下方法强制线程终止:

Thread.CurrentThread.Abort();

Thread.Abort()< /code> 通常被认为是一种不好的做法,但在这里它的危险性要小一些,因为您正在中止自己,因此不会将异常注入到潜在的令人讨厌的位置(您还知道该线程不在非托管上下文中,因此它将立即中止。)这仍然是一个令人讨厌的黑客行为,但第三方应用程序并没有给你太多选择。 ThreadAbortException 无法“停止”,因此第三方代码一旦到达其异常处理程序的末尾,就会终止其线程(即使它们试图吞掉它)。如果第三方库真的很讨厌,它可能会在其 catch 或 finally 块中调用大量代码,甚至使用肮脏的技巧来保持活动状态,例如启动其他线程,但这样做必须非常恶意。

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

如果您确实不信任该库(并且不想给它机会即使在其 catch 和 finally 块中也能保持活动状态),您可以使用以下命令显式编组到 UI 线程:阻止调用(以友好的方式显示错误消息),然后调用Environment.FailFast()来终止您的进程。这是一种特别严厉的终止方式(它不会调用任何清理代码,并且会尽快地销毁进程),但如果应用程序状态变得非常损坏,它可以最大限度地减少任何潜在破坏性副作用的可能性。这里需要注意的一件事是,UI 线程可能会被与第三方代码相关的其他一些 UI 调用阻塞。如果发生这种情况,应用程序将陷入死锁。同样,这对它来说是一件非常恶意的事情,所以你可以忽略它。

If you're hooking the AppDomain.UnhandledException event, then the issue isn't the fact that they might be calling back on a background thread, but rather than the third-party library is explicitly swallowing exceptions thrown by the handlers. This is a badly behaving library, but, since you're writing the event handler code, you can catch the exceptions in the event handler and force the application to shut down.

Since the third-party library can't be stopped by throwing an exception, you can force the thread to terminate by calling:

Thread.CurrentThread.Abort();

Thread.Abort() is generally considered a bad practice, but it's slightly less dangerous here, as you are aborting yourself and therefore won't be injecting the exception into potentially nasty locations (you also know that the thread is not in an unmanaged context, so it will abort right away.) It's still a nasty hack, but the third-party application isn't giving you much choice. ThreadAbortException cannot be 'stopped', so the third-party code will terminate its thread as soon as it reaches the end of its exception handlers (even if they try to swallow it). If the third-party library is really nasty, it might invoke lots of code in its catch or finally blocks, even using dirty tricks to stay alive like launching other threads, but it would have to be pretty malicious to do this.

To get the friendly error message behavior, you can marshal the Exception to your UI thread using a SynchronizationContext or Dispatcher to call your exception-handler display (the easiest way may be to just re-throw the exception; I recommend embedding it as an InnerException so that you don't lose stack trace.)

If you really distrust the library (and don't want to give it the opportunity to stay alive even through its catch and finally blocks), you can explicitly marshal to the UI thread with a blocking invoke (to display your error message in a friendly way) and then call Environment.FailFast() to kill your process. This is a particularly harsh way to terminate (it will not call any cleanup code and literally tears down the process as quickly as possible), but it minimizes the possibility for any potentially damaging side effects if application state has become very corrupted. One possible thing to watch for here is that the UI thread could be blocked by some other UI invocation tied to the third-party code. If this happens, the application will deadlock. Again, this would be a pretty malicious thing for it to do, so you can probably ignore it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文