Bagikan melalui


AppDomain.FirstChanceException Kejadian

Definisi

Terjadi ketika pengecualian dilemparkan dalam kode terkelola, sebelum runtime mencari tumpukan panggilan untuk penangan pengecualian di domain aplikasi.

public:
 event EventHandler<System::Runtime::ExceptionServices::FirstChanceExceptionEventArgs ^> ^ FirstChanceException;
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>? FirstChanceException;
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
member this.FirstChanceException : EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> 
[<add: System.Security.SecurityCritical>]
[<remove: System.Security.SecurityCritical>]
member this.FirstChanceException : EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> 
Public Custom Event FirstChanceException As EventHandler(Of FirstChanceExceptionEventArgs) 

Jenis Acara

Atribut

Contoh

Contoh berikut membuat serangkaian domain aplikasi bernama AD0 melalui AD3, dengan Worker objek di setiap domain aplikasi. Setiap Worker objek memiliki referensi ke Worker objek di domain aplikasi berikutnya, kecuali di Worker domain aplikasi terakhir. Peristiwa FirstChanceException ini ditangani di semua domain aplikasi kecuali AD1.

Catatan

Selain contoh ini, yang menunjukkan pemberitahuan pengecualian kesempatan pertama di beberapa domain aplikasi, Anda dapat menemukan kasus penggunaan sederhana di Cara: Menerima Pemberitahuan Pengecualian First-Chance.

Ketika domain aplikasi telah dibuat, domain aplikasi default memanggil TestException metode untuk domain aplikasi pertama. Setiap Worker objek memanggil TestException metode untuk domain aplikasi berikutnya, sampai yang terakhir Worker melemparkan pengecualian yang ditangani atau tidak tertangani. Dengan demikian, utas saat ini melewati semua domain aplikasi, dan TestException ditambahkan ke tumpukan di setiap domain aplikasi.

Ketika objek terakhir Worker menangani pengecualian, FirstChanceException peristiwa hanya dinaikkan di domain aplikasi terakhir. Domain aplikasi lainnya tidak pernah mendapatkan kesempatan untuk menangani pengecualian, sehingga peristiwa tidak dinaikkan.

Ketika objek terakhir Worker tidak menangani pengecualian, FirstChanceException peristiwa dinaikkan di setiap domain aplikasi yang memiliki penanganan aktivitas. Setelah setiap penanganan aktivitas selesai, tumpukan terus melepas lelah hingga pengecualian ditangkap oleh domain aplikasi default.

Catatan

Untuk melihat bagaimana tampilan tumpukan tumbuh saat peristiwa dinaikkan lebih dekat dan lebih dekat ke domain aplikasi default, ubah e.Exception.Message menjadi e.ExceptionFirstChanceHandler di penanganan aktivitas. Perhatikan bahwa ketika TestException dipanggil di seluruh batas domain aplikasi, itu muncul dua kali: sekali untuk proksi dan sekali untuk lonjakan.

using System;
using System.Reflection;
using System.Runtime.ExceptionServices;

class FirstChanceExceptionSnippet
{
    static void Main()
    {
        AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;

        // Create a set of application domains, with a Worker object in each one.
        // Each Worker object creates the next application domain.
        AppDomain ad = AppDomain.CreateDomain("AD0");
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                                typeof(Worker).Assembly.FullName, "Worker");
        w.Initialize(0, 3);

        Console.WriteLine("\r\nThe last application domain throws an exception and catches it:");
        Console.WriteLine();
        w.TestException(true);

        try
        {
            Console.WriteLine(
                "\r\nThe last application domain throws an exception and does not catch it:");
            Console.WriteLine();
            w.TestException(false);
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine("ArgumentException caught in {0}: {1}",
                AppDomain.CurrentDomain.FriendlyName, ex.Message);
        }
    }

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
}

public class Worker : MarshalByRefObject
{
    private AppDomain ad = null;
    private Worker w = null;

    public void Initialize(int count, int max)
    {
        // Handle the FirstChanceException event in all application domains except
        // AD1.
        if (count != 1)
        {
            AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;
        }

        // Create another application domain, until the maximum is reached.
        // Field w remains null in the last application domain, as a signal
        // to TestException().
        if (count < max)
        {
            int next = count + 1;
            ad = AppDomain.CreateDomain("AD" + next);
            w = (Worker) ad.CreateInstanceAndUnwrap(
                             typeof(Worker).Assembly.FullName, "Worker");
            w.Initialize(next, max);
        }
    }

    public void TestException(bool handled)
    {
        // As long as there is another application domain, call TestException() on
        // its Worker object. When the last application domain is reached, throw a
        // handled or unhandled exception.
        if (w != null)
        {
            w.TestException(handled);
        }
        else if (handled)
        {
            try
            {
                throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine("ArgumentException caught in {0}: {1}",
                    AppDomain.CurrentDomain.FriendlyName, ex.Message);
            }
        }
        else
        {
            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
}

/* This example produces output similar to the following:

The last application domain throws an exception and catches it:

FirstChanceException event raised in AD3: Thrown in AD3
ArgumentException caught in AD3: Thrown in AD3

The last application domain throws an exception and does not catch it:

FirstChanceException event raised in AD3: Thrown in AD3
FirstChanceException event raised in AD2: Thrown in AD3
FirstChanceException event raised in AD0: Thrown in AD3
FirstChanceException event raised in Example.exe: Thrown in AD3
ArgumentException caught in Example.exe: Thrown in AD3
 */
open System
open System.Runtime.ExceptionServices

let firstChanceHandler _ (e: FirstChanceExceptionEventArgs) =
    printfn $"FirstChanceException event raised in {AppDomain.CurrentDomain.FriendlyName}: {e.Exception.Message}"

type Worker() =
    inherit MarshalByRefObject()

    let mutable w = Unchecked.defaultof<Worker>

    member _.Initialize(count, max) =
        // Handle the FirstChanceException event in all application domains except
        // AD1.
        if count <> 1 then
            AppDomain.CurrentDomain.FirstChanceException.AddHandler firstChanceHandler

        // Create another application domain, until the maximum is reached.
        // Field w remains null in the last application domain, as a signal
        // to TestException().
        if count < max then
            let next = count + 1
            let ad = AppDomain.CreateDomain("AD" + string next)
            w <-
                ad.CreateInstanceAndUnwrap(typeof<Worker>.Assembly.FullName, "Worker") :?> Worker
            w.Initialize(next, max)

    member _.TestException(handled) =
        // As long as there is another application domain, call TestException() on
        // its Worker object. When the last application domain is reached, throw a
        // handled or unhandled exception.
        if isNull (box w) then
            w.TestException handled
        elif handled then
            try
                raise (ArgumentException $"Thrown in {AppDomain.CurrentDomain.FriendlyName}")
            with :? ArgumentException as ex ->
                printfn $"ArgumentException caught in {AppDomain.CurrentDomain.FriendlyName}: {ex.Message}"
        else
            raise (ArgumentException $"Thrown in {AppDomain.CurrentDomain.FriendlyName}")

AppDomain.CurrentDomain.FirstChanceException.AddHandler firstChanceHandler

// Create a set of application domains, with a Worker object in each one.
// Each Worker object creates the next application domain.
let ad = AppDomain.CreateDomain "AD0"
let w = ad.CreateInstanceAndUnwrap(typeof<Worker>.Assembly.FullName, "Worker") :?> Worker
w.Initialize(0, 3)

printfn "\nThe last application domain throws an exception and catches it:\n"
w.TestException true

try
    printfn "\nThe last application domain throws an exception and does not catch it:\n"
    w.TestException false
with :? ArgumentException as ex ->
    printfn"ArgumentException caught in {AppDomain.CurrentDomain.FriendlyName}: {ex.Message}"

(* This example produces output similar to the following:

The last application domain throws an exception and catches it:

FirstChanceException event raised in AD3: Thrown in AD3
ArgumentException caught in AD3: Thrown in AD3

The last application domain throws an exception and does not catch it:

FirstChanceException event raised in AD3: Thrown in AD3
FirstChanceException event raised in AD2: Thrown in AD3
FirstChanceException event raised in AD0: Thrown in AD3
FirstChanceException event raised in Example.exe: Thrown in AD3
ArgumentException caught in Example.exe: Thrown in AD3
 *)
Imports System.Reflection
Imports System.Runtime.ExceptionServices

Class Example

    Shared Sub Main()
    
        AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceHandler

        ' Create a set of application domains, with a Worker object in each one.
        ' Each Worker object creates the next application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("AD0")
        Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                GetType(Worker).Assembly.FullName, "Worker"),
                                Worker)
        w.Initialize(0, 3)

        Console.WriteLine(vbCrLf & "The last application domain throws an exception and catches it:")
        Console.WriteLine()
        w.TestException(true)

        Try
            Console.WriteLine(vbCrLf & 
                "The last application domain throws an exception and does not catch it:")
            Console.WriteLine()
            w.TestException(false) 

        Catch ex As ArgumentException
        
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message)
        End Try
    End Sub

    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)
    
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
End Class

Public Class Worker
    Inherits MarshalByRefObject

    Private ad As AppDomain = Nothing
    Private w As Worker = Nothing

    Public Sub Initialize(ByVal count As Integer, ByVal max As Integer)
    
        ' Handle the FirstChanceException event in all application domains except
        ' AD1.
        If count <> 1
        
            AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceHandler

        End If

        ' Create another application domain, until the maximum is reached.
        ' Field w remains Nothing in the last application domain, as a signal 
        ' to TestException(). 
        If count < max
            Dim nextAD As Integer = count + 1
            ad = AppDomain.CreateDomain("AD" & nextAD)
            w = CType(ad.CreateInstanceAndUnwrap(
                      GetType(Worker).Assembly.FullName, "Worker"),
                      Worker)
            w.Initialize(nextAD, max)
        End If
    End Sub

    Public Sub TestException(ByVal handled As Boolean)
    
        ' As long as there is another application domain, call TestException() on
        ' its Worker object. When the last application domain is reached, throw a
        ' handled or unhandled exception.
        If w IsNot Nothing
        
            w.TestException(handled)

        Else If handled
        
            Try
                Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)

            Catch ex As ArgumentException
            
                Console.WriteLine("ArgumentException caught in {0}: {1}", 
                    AppDomain.CurrentDomain.FriendlyName, ex.Message)
            End Try
        Else
        
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End If
    End Sub

    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)
    
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
End Class

' This example produces output similar to the following:
'
'The last application domain throws an exception and catches it:
'
'FirstChanceException event raised in AD3: Thrown in AD3
'ArgumentException caught in AD3: Thrown in AD3
'
'The last application domain throws an exception and does not catch it:
'
'FirstChanceException event raised in AD3: Thrown in AD3
'FirstChanceException event raised in AD2: Thrown in AD3
'FirstChanceException event raised in AD0: Thrown in AD3
'FirstChanceException event raised in Example.exe: Thrown in AD3
'ArgumentException caught in Example.exe: Thrown in AD3

Keterangan

Kejadian ini hanya pemberitahuan. Menangani kejadian ini tidak menangani pengecualian atau memengaruhi penanganan pengecualian berikutnya dengan cara apa pun. Setelah peristiwa dinaikkan dan penanganan aktivitas dipanggil, runtime bahasa umum (CLR) mulai mencari handler untuk pengecualian tersebut. FirstChanceException menyediakan domain aplikasi dengan kesempatan pertama untuk memeriksa pengecualian terkelola apa pun.

Peristiwa dapat ditangani per domain aplikasi. Jika utas melewati beberapa domain aplikasi saat menjalankan panggilan, peristiwa dinaikkan di setiap domain aplikasi yang telah mendaftarkan penanganan aktivitas, sebelum CLR mulai mencari penangan pengecualian yang cocok di domain aplikasi tersebut. Setelah peristiwa ditangani, pencarian dilakukan untuk penangan pengecualian yang cocok di domain aplikasi tersebut. Jika tidak ada yang ditemukan, peristiwa akan dimunculkan di domain aplikasi berikutnya.

Anda harus menangani semua pengecualian yang terjadi di penanganan aktivitas untuk peristiwa tersebut FirstChanceException . Jika tidak, FirstChanceException dinaikkan secara rekursif. Ini dapat mengakibatkan luapan tumpukan dan penghentian aplikasi. Kami menyarankan agar Anda menerapkan penanganan aktivitas untuk peristiwa ini sebagai wilayah eksekusi (CER) yang dibatasi, untuk menjaga pengecualian terkait infrastruktur seperti kehabisan memori atau luapan tumpukan agar tidak memengaruhi komputer virtual saat pemberitahuan pengecualian sedang diproses.

Kejadian ini tidak dinaikkan untuk pengecualian yang menunjukkan kerusakan status proses, seperti pelanggaran akses, kecuali penanganan aktivitas kritis terhadap keamanan dan memiliki HandleProcessCorruptedStateExceptionsAttribute atribut .

Runtime bahasa umum menangguhkan pembatalakuan utas saat peristiwa pemberitahuan ini sedang ditangani.

Berlaku untuk

Lihat juga