C# .NET - 实现“捕获所有异常处理程序”的最佳方法是什么

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/219594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:38:04  来源:igfitidea点击:

.NET - What's the best way to implement a "catch all exceptions handler"

c#.netexceptionexception-handling

提问by TimothyP

I'm wondering what the best way is to have a "if all else fails catch it".

我想知道最好的方法是“如果所有其他方法都失败了,就抓住它”。

I mean, you're handling as much exceptions as possible in your application, but still there are bound to be bugs, so I need to have something that catches all unhandled exceptions so I can collect information and store them in a database or submit them to a web service.

我的意思是,您在应用程序中处理了尽可能多的异常,但仍然肯定会有错误,所以我需要一些东西来捕获所有未处理的异常,以便我可以收集信息并将它们存储在数据库中或提交它们到网络服务。

Does the AppDomain.CurrentDomain.UnhandledException event capture everything? Even if the application is multithreaded?

AppDomain.CurrentDomain.UnhandledException 事件是否捕获所有内容?即使应用程序是多线程的?

Side note: Windows Vista exposes native API functions that allow any application to recover itself after a crash... can't think of the name now... but I'd rather not use it, as many of our users are still using Windows XP.

旁注:Windows Vista 公开了本机 API 函数,允许任何应用程序在崩溃后自行恢复......现在想不出这个名字......但我宁愿不使用它,因为我们的许多用户仍在使用视窗 XP。

采纳答案by bohdan_trotsenko

I have just played with AppDomain's UnhandledException behavior, (this is the last stage the unhandled exception is registered at)

我刚刚玩过 AppDomain 的 UnhandledException 行为,(这是注册未处理异常的最后阶段)

Yes, after processing the event handlers your application will be terminated and the nasty "... program stopped working dialog" shown.

是的,处理完事件处理程序后,您的应用程序将被终止,并显示令人讨厌的“...程序停止工作对话框”。

:) You stillcan avoid that.

:) 你仍然可以避免这种情况。

Check out:

查看:

class Program
{
    void Run()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        Console.WriteLine("Press enter to exit.");

        do
        {
            (new Thread(delegate()
            {
                throw new ArgumentException("ha-ha");
            })).Start();

        } while (Console.ReadLine().Trim().ToLowerInvariant() == "x");


        Console.WriteLine("last good-bye");
    }

    int r = 0;

    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Interlocked.Increment(ref r);
        Console.WriteLine("handled. {0}", r);
        Console.WriteLine("Terminating " + e.IsTerminating.ToString());

        Thread.CurrentThread.IsBackground = true;
        Thread.CurrentThread.Name = "Dead thread";            

        while (true)
            Thread.Sleep(TimeSpan.FromHours(1));
        //Process.GetCurrentProcess().Kill();
    }

    static void Main(string[] args)
    {
        Console.WriteLine("...");
        (new Program()).Run();
    }
}

P.S.Do handle the unhandled for Application.ThreadException (WinForms) or DispatcherUnhandledException (WPF) at the higher level.

PS 请在更高级别处理未处理的 Application.ThreadException (WinForms) 或 DispatcherUnhandledException (WPF)。

回答by ine

In ASP.NET, you use the Application_Errorfunction in the Global.asaxfile.

在 ASP.NET 中,您使用文件中的Application_Error函数Global.asax

In WinForms, you use the MyApplication_UnhandledExceptionin the ApplicationEventsfile

在 WinForms 中,您MyApplication_UnhandledExceptionApplicationEvents文件中使用

Both of these functions are called if an unhandled exception occurs in your code. You can log the exception and present a nice message to the user from these functions.

如果您的代码中出现未处理的异常,则会调用这两个函数。您可以记录异常并从这些函数中向用户显示一条好消息。

回答by Bogdan Maxim

For WinForms, don't forget to attach to the current Thread's unhandled exception event too (especially if you are using multi threading).

对于 WinForms,也不要忘记附加到当前线程的未处理异常事件(尤其是在使用多线程时)。

Some links on best practices hereand hereand here (probably the best exception handling article for .net)

一些关于最佳实践的链接在这里这里这里(可能是 .net 的最佳异常处理文章)

回答by Bob Nadler

For Winform applications, in addition to AppDomain.CurrentDomain.UnhandledException I also use Application.ThreadExceptionand Application.SetUnhandledExceptionMode(w/ UnhandledExceptionMode.CatchException). This combination seems to catch everything.

对于 Winform 应用程序,除了 AppDomain.CurrentDomain.UnhandledException 我还使用Application.ThreadExceptionApplication.SetUnhandledExceptionMode(w/ UnhandledExceptionMode.CatchException)。这种组合似乎抓住了一切。

回答by Steven A. Lowe

On the main thread, you have the following options:

在主线程上,您有以下选项:

For other threads:

对于其他线程:

  • Secondary threads have no unhandled-exceptions; use SafeThread
  • Worker threads: (timer, threadpool) there is no safety net at all!
  • 辅助线程没有未处理的异常;使用安全线程
  • 工作线程:(定时器,线程池)根本没有安全网!

Bear in mind that these events do not handleexceptions, they merely reportthem to the application--often when it is far too late to do anything useful/sane about them

请记住,这些事件不处理异常,它们只是将它们报告给应用程序——通常在对它们做任何有用/理智的事情时已经太晚了

Logging exceptions is good, but monitoring applications is better ;-)

记录异常很好,但监控应用程序更好;-)

Caveat: I am the author of the SafeThreadarticle.

警告:我是SafeThread文章的作者。

回答by Ryan Abbott

There's also a cool thing called ELMAHthat will log any ASP.NET errors that occur in a web application. I know you're asking about a Winform App solution, but I felt this could be beneficial to anyone needing this type of thing on a web app. We use it where I work and it's been very helpful in debugging (especially on production servers!)

还有一个很酷的东西叫做ELMAH,它会记录 Web 应用程序中发生的任何 ASP.NET 错误。我知道您在询问 Winform 应用程序解决方案,但我觉得这对需要在 Web 应用程序上使用此类内容的任何人都有好处。我们在我工作的地方使用它,它对调试非常有帮助(尤其是在生产服务器上!)

Here's some features that it has (pulled right off the page):

这是它具有的一些功能(从页面上直接拉出):

  • Logging of nearly all unhandled exceptions.
  • A web page to remotely view the entire log of recoded exceptions.
  • A web page to remotely view the full details of any one logged exception.
  • In many cases, you can review the original yellow screen of death that ASP.NET generated for a given exception, even with customErrors mode turned off.
  • An e-mail notification of each error at the time it occurs.
  • An RSS feed of the last 15 errors from the log.
  • A number of backing storage implementations for the log, including in-memory, Microsoft SQL Server and several contributed by the community.
  • 记录几乎所有未处理的异常。
  • 用于远程查看记录异常的整个日志的网页。
  • 用于远程查看任何记录异常的完整详细信息的网页。
  • 在许多情况下,您可以查看 ASP.NET 为给定异常生成的原始黄屏死机,即使关闭了 customErrors 模式。
  • 每个错误发生时的电子邮件通知。
  • 日志中最后 15 个错误的 RSS 提要。
  • 日志的许多后备存储实现,包括内存中、Microsoft SQL Server 和社区贡献的一些。

回答by jezell

You can monitor most exceptions in that handler even in multithreaded apps, but .NET (starting with 2.0) won't allow you to cancel unhandled exceptions unless you enable the 1.1 compatibility mode. When that happens the AppDomain will be shut down no matter what. The best you could do is launch the app in a different AppDomain so that you can handle this exception and create a new AppDomain to restart the app.

即使在多线程应用程序中,您也可以监视该处理程序中的大多数异常,但 .NET(从 2.0 开始)不允许您取消未处理的异常,除非您启用 1.1 兼容模式。当这种情况发生时,无论如何 AppDomain 都会被关闭。您能做的最好的事情是在不同的 AppDomain 中启动应用程序,以便您可以处理此异常并创建新的 AppDomain 以重新启动应用程序。

回答by Yordan Georgiev

I am using the following approach, which works and reduces greatly the amount of code ( yet I am not sure if there is a better way or what the pitfalls of it might be. Whenever you call: I quess the quys giving minuses would be polite enough to clarify their actions ; )

我正在使用以下方法,该方法有效并大大减少了代码量(但我不确定是否有更好的方法或它的陷阱可能是什么。无论何时你打电话:我问 quys 给出缺点会很有礼貌足以澄清他们的行为;)

try 
{
    CallTheCodeThatMightThrowException()
 }
catch (Exception ex)
{
    System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
    Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch

And here is the ErrorHandler code : Just to make clear- : objUser - is the object modelling the appusers ( you might get info such as domain name , department , region etc. for logging purposes ILog logger - is the logging object - e.g. the one performing the logging activities StackTrace st - the StackTrace object giving you debugging info for your app

这里是 ErrorHandler 代码: 只是为了说明 - :objUser - 是对应用程序用户建模的对象(您可能会获得诸如域名、部门、​​地区等信息以用于日志记录目的 ILog logger - 是日志记录对象 - 例如执行日志记录活动 StackTrace st - StackTrace 对象为您提供应用程序的调试信息

using System;
using log4net; //or another logging platform

namespace GenApp.Utils
{
  public class ErrorHandler
  {
    public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
    {
      if (ex is NullReferenceException)
      { 
      //do stuff for this ex type
      } //eof if

      if (ex is System.InvalidOperationException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.IndexOutOfRangeException) 
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.Data.SqlClient.SqlException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is System.FormatException)
      {
        //do stuff for this ex type
      } //eof if

      if (ex is Exception)
      {
        //do stuff for this ex type
      } //eof catch

    } //eof method 

  }//eof class 
} //eof namesp

回答by Corey Trager

In a manged GUI app, by default, exceptions that originate in the GUI thread are handled by whatever is assigned to the Application.ThreadException.

在托管 GUI 应用程序中,默认情况下,源自 GUI 线程的异常由分配给 Application.ThreadException 的任何内容处理。

Exceptions that originate in the other threads are handled by AppDomain.CurrentDomain.UnhandledException.

源自其他线程的异常由 AppDomain.CurrentDomain.UnhandledException 处理。

If you want your GUI thread exceptions to work just like your-non GUI ones, so that they get handled by AppDomain.CurrentDomain.UnhandledException, you can do this:

如果您希望 GUI 线程异常像非 GUI 线程异常一样工作,以便它们由 AppDomain.CurrentDomain.UnhandledException 处理,您可以这样做:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);

An advantage to catching the GUI thread exceptions using ThreadException is that you can give the use the options of letting the app continue. To make sure no config files are overriding default behavior, you can call:

使用 ThreadException 捕获 GUI 线程异常的一个优点是您可以为用户提供让应用程序继续运行的选项。为确保没有配置文件覆盖默认行为,您可以调用:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

You are still vulnerable to exceptions from badly behaved native dlls. If a native dll installs its own handler using Win32 SetUnhandledExceptionFilter, it is supposed to save the pointer to the previous filter and call it too. If it doesn't do that, your handler wont' get called.

您仍然容易受到来自行为不良的本机 dll 的异常的影响。如果本机 dll 使用 Win32 SetUnhandledExceptionFilter 安装自己的处理程序,它应该保存指向前一个过滤器的指针并调用它。如果它不这样做,您的处理程序将不会被调用。