AppDomain.UnhandledException 事件

定义

当某个异常未被捕获时出现。

public:
 event UnhandledExceptionEventHandler ^ UnhandledException;
public:
 virtual event UnhandledExceptionEventHandler ^ UnhandledException;
public event UnhandledExceptionEventHandler? UnhandledException;
public event UnhandledExceptionEventHandler UnhandledException;
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event UnhandledExceptionEventHandler UnhandledException;
member this.UnhandledException : UnhandledExceptionEventHandler 
[<add: System.Security.SecurityCritical>]
[<remove: System.Security.SecurityCritical>]
member this.UnhandledException : UnhandledExceptionEventHandler 
Public Custom Event UnhandledException As UnhandledExceptionEventHandler 

事件类型

UnhandledExceptionEventHandler

实现

属性

示例

以下示例演示了该 UnhandledException 事件。 它定义事件处理程序, MyHandler每当在默认应用程序域中引发未经处理的异常时,就会调用该处理程序。 然后,它会引发两个异常。 第一个由 try/catch 块处理。 第二个是未经处理的, MyHandle 并在应用程序终止之前调用例程。

// The example should be compiled with the /clr:pure compiler option.
using namespace System;
using namespace System::Security::Permissions;

public ref class Example
{


private:
   static void MyHandler(Object^ sender, UnhandledExceptionEventArgs^ args)
   {
      Exception^ e = dynamic_cast<Exception^>(args->ExceptionObject);
      Console::WriteLine( "MyHandler caught : {0}", e->Message );
      Console::WriteLine("Runtime terminating: {0}", args->IsTerminating);
   }
   
public: 
   [SecurityPermissionAttribute( SecurityAction::Demand, ControlAppDomain = true )]
   static void Main()
   {
      AppDomain^ currentDomain = AppDomain::CurrentDomain;
      currentDomain->UnhandledException += gcnew UnhandledExceptionEventHandler(Example::MyHandler);
      try
      {
         throw gcnew Exception("1");
      }
      catch (Exception^ e) 
      {
         Console::WriteLine( "Catch clause caught : {0}\n", e->Message );
      }

      throw gcnew Exception("2");
   }
};

void main()
{
   Example::Main();
}   
// The example displays the following output:
//       Catch clause caught : 1
//       
//       MyHandler caught : 2
//       Runtime terminating: True
//       
//       Unhandled Exception: System.Exception: 2
//          at Example.Main()
//          at mainCRTStartup(String[] arguments)
using System;

public class Example
{
   public static void Main()
   {
      AppDomain currentDomain = AppDomain.CurrentDomain;
      currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);

      try {
         throw new Exception("1");
      } catch (Exception e) {
         Console.WriteLine("Catch clause caught : {0} \n", e.Message);
      }

      throw new Exception("2");
   }

   static void MyHandler(object sender, UnhandledExceptionEventArgs args)
   {
      Exception e = (Exception) args.ExceptionObject;
      Console.WriteLine("MyHandler caught : " + e.Message);
      Console.WriteLine("Runtime terminating: {0}", args.IsTerminating);
   }
}
// The example displays the following output:
//       Catch clause caught : 1
//
//       MyHandler caught : 2
//       Runtime terminating: True
//
//       Unhandled Exception: System.Exception: 2
//          at Example.Main()
open System
open System.Security.Permissions

let myHandler _ (args: UnhandledExceptionEventArgs) =
    let e = args.ExceptionObject :?> Exception
    printfn $"MyHandler caught : {e.Message}"
    printfn $"Runtime terminating: {args.IsTerminating}"

[<EntryPoint>]
let main _ =
    let currentDomain = AppDomain.CurrentDomain
    currentDomain.UnhandledException.AddHandler(UnhandledExceptionEventHandler myHandler)

    try
        failwith "1"
    with e ->
        printfn $"Catch clause caught : {e.Message} \n"

    failwith "2"

// The example displays the following output:
//       Catch clause caught : 1
//
//       MyHandler caught : 2
//       Runtime terminating: True
//
//       Unhandled Exception: System.Exception: 2
//          at Example.main()
Module Example
   Sub Main()
      Dim currentDomain As AppDomain = AppDomain.CurrentDomain
      AddHandler currentDomain.UnhandledException, AddressOf MyHandler
      
      Try
         Throw New Exception("1")
      Catch e As Exception
         Console.WriteLine("Catch clause caught : " + e.Message)
         Console.WriteLine()
      End Try
      
      Throw New Exception("2")
   End Sub
   
   Sub MyHandler(sender As Object, args As UnhandledExceptionEventArgs)
      Dim e As Exception = DirectCast(args.ExceptionObject, Exception)
      Console.WriteLine("MyHandler caught : " + e.Message)
      Console.WriteLine("Runtime terminating: {0}", args.IsTerminating)
   End Sub
End Module
' The example displays the following output:
'       Catch clause caught : 1
'       
'       MyHandler caught : 2
'       Runtime terminating: True
'       
'       Unhandled Exception: System.Exception: 2
'          at Example.Main()

注解

此事件提供未捕获异常的通知。 它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。 如果有足够的有关应用程序状态的信息可用,可能会执行其他操作,例如保存程序数据以供以后恢复。 建议谨慎,因为未处理异常时程序数据可能会损坏。

备注

在.NET Framework版本 1.0 和 1.1 中,在引发此事件之前,应用程序终止和调试选项将报告给用户,而不是之后。

可以在任何应用程序域中处理此事件。 但是,在发生异常的应用程序域中不一定引发该事件。 仅当线程的整个堆栈未找到适用的异常处理程序时,才会撤消异常,因此可以引发事件的第一个位置位于线程发起的应用程序域中。

备注

在.NET Framework版本 1.0 和 1.1 中,此事件仅适用于启动应用程序时由系统创建的默认应用程序域。 如果应用程序创建其他应用程序域,请在这些应用程序域中为此事件指定委托无效。

UnhandledException如果事件在默认应用程序域中处理,则会在任何线程中引发任何未经处理的异常,无论线程启动的应用程序域是什么。 如果线程在具有事件处理程序的应用程序 UnhandledException域中启动,则会在该应用程序域中引发该事件。 如果该应用程序域不是默认应用程序域,并且默认应用程序域中也存在事件处理程序,则会在这两个应用程序域中引发该事件。

例如,假设线程在应用程序域“AD1”中启动,在应用程序域“AD2”中调用方法,并从中调用应用程序域“AD3”中的方法,其中引发异常。 可以引发事件的第一个应用程序域 UnhandledException 是“AD1”。 如果该应用程序域不是默认应用程序域,则还可以在默认应用程序域中引发该事件。

备注

公共语言运行时在执行事件的事件处理程序 UnhandledException 时暂停线程中止。

如果事件处理程序具有具有 ReliabilityContractAttribute 相应标志的属性,则事件处理程序被视为受约束的执行区域。

从 .NET Framework 4 开始,对于损坏进程状态(如堆栈溢出或访问冲突)的异常,不会引发此事件,除非事件处理程序是安全关键且具有HandleProcessCorruptedStateExceptionsAttribute属性。

在.NET Framework版本 1.0 和 1.1 中,运行时捕获了非主应用程序线程的线程中发生的未经处理的异常,因此不会导致应用程序终止。 因此, UnhandledException 可以在不终止应用程序的情况下引发事件。 从 .NET Framework 版本 2.0 开始,删除了子线程中未经处理的异常的后退,因为此类无提示故障的累积效果包括性能下降、损坏的数据和锁定,所有这些操作都难以调试。 有关详细信息,包括运行时未终止的情况列表,请参阅 托管线程中的异常

若要为此事件注册事件处理程序,必须具有所需的权限,或引发一个 SecurityException

有关处理事件的详细信息,请参阅 处理和引发事件

未处理的异常的其他事件

对于某些应用程序模型,如果主应用程序线程中发生未经处理的异常, UnhandledException 事件可以被其他事件抢占。

在使用Windows 窗体的应用程序中,主应用程序线程中的未经处理的异常会导致Application.ThreadException引发事件。 如果处理此事件,则默认行为是未处理的异常不会终止应用程序,尽管应用程序处于未知状态。 在这种情况下, UnhandledException 不会引发该事件。 可以使用应用程序配置文件更改此行为,或者通过使用 Application.SetUnhandledExceptionMode 方法将模式 UnhandledExceptionMode.ThrowException 更改为挂接事件处理程序之前 ThreadException 。 这仅适用于主应用程序线程。 对于在其他线程中引发的未经处理的异常,将引发该 UnhandledException 事件。

从 2005 Microsoft Visual Studio开始,Visual Basic应用程序框架为主应用程序线程中的未经处理的异常提供了另一个事件。 请参阅事件 WindowsFormsApplicationBase.UnhandledException 。 此事件具有一个事件参数对象,该对象的名称与事件参数对象使用 AppDomain.UnhandledException的名称相同,但具有不同的属性。 具体而言,此事件参数对象具有一个 ExitApplication 属性,该属性允许应用程序继续运行,忽略未经处理的异常 (并将应用程序保留为未知状态) 。 在这种情况下, AppDomain.UnhandledException 不会引发该事件。

适用于