Bagikan melalui


Cara: Menerima Pemberitahuan Pengecualian Kesempatan Pertama

Catatan

Artikel ini khusus untuk .NET Framework. Ini tidak berlaku untuk implementasi .NET yang lebih baru, termasuk .NET 6 dan versi yang lebih baru.

Peristiwa FirstChanceException dari kelas AppDomain memungkinkan Anda menerima pemberitahuan bahwa pengecualian telah ditampilkan, sebelum runtime bahasa umum mulai mencari penanganan pengecualian.

Peristiwa dimunculkan di tingkat domain aplikasi. Sebuah utas eksekusi dapat melewati beberapa domain aplikasi, sehingga pengecualian yang tidak ditangani di satu domain aplikasi dapat ditangani di domain aplikasi lain. Pemberitahuan terjadi di setiap domain aplikasi yang telah menambahkan penanganan untuk peristiwa tersebut, sampai domain aplikasi menangani pengecualian.

Prosedur dan contoh dalam artikel ini menunjukkan cara menerima pemberitahuan pengecualian kesempatan pertama dalam program sederhana yang memiliki satu domain aplikasi, dan dalam domain aplikasi yang Anda buat.

Untuk contoh yang lebih kompleks yang mencakup beberapa domain aplikasi, lihat contoh untuk peristiwa FirstChanceException.

Menerima Pemberitahuan Pengecualian Kesempatan Pertama di Domain Aplikasi Default

Dalam prosedur berikut, titik masuk untuk aplikasi, metode Main(), berjalan di domain aplikasi default.

Untuk menunjukkan pemberitahuan pengecualian kesempatan pertama di domain aplikasi default

  1. Tentukan penanganan aktivitas untuk peristiwa FirstChanceException, menggunakan fungsi lambda, dan lampirkan ke peristiwa. Dalam contoh ini, penanganan aktivitas mencetak nama domain aplikasi tempat peristiwa ditangani dan properti Message pengecualian.

    using System;
    using System.Runtime.ExceptionServices;
    
    class Example
    {
        static void Main()
        {
            AppDomain.CurrentDomain.FirstChanceException +=
                (object source, FirstChanceExceptionEventArgs e) =>
                {
                    Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                        AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
                };
    
    Imports System.Runtime.ExceptionServices
    
    Class Example
    
        Shared Sub Main()
    
            AddHandler AppDomain.CurrentDomain.FirstChanceException,
                       Sub(source As Object, e As FirstChanceExceptionEventArgs)
                           Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                                             AppDomain.CurrentDomain.FriendlyName,
                                             e.Exception.Message)
                       End Sub
    
  2. Tampilkan pengecualian dan tangkap pengecualian tersebut. Sebelum runtime bahasa umum menemukan penanganan pengecualian, peristiwa FirstChanceException dimunculkan dan menampilkan pesan. Pesan ini diikuti oleh pesan yang ditampilkan oleh penanganan pengecualian.

    try
    {
        throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
    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
    
  3. Tampilkan pengecualian, tetapi jangan ditangkap. Sebelum runtime bahasa umum mencari penanganan pengecualian, peristiwa FirstChanceException dimunculkan dan menampilkan pesan. Tidak ada penanganan pengecualian, sehingga aplikasi berhenti.

            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }
    
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End Sub
    End Class
    

    Kode yang ditampilkan dalam tiga langkah pertama dari prosedur ini membentuk aplikasi konsol yang lengkap. Output dari aplikasi bervariasi, tergantung pada nama file .exe, karena nama domain aplikasi default terdiri dari nama dan ekstensi file .exe. Lihat berikut ini untuk sampel output.

    /* This example produces output similar to the following:
    
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    ArgumentException caught in Example.exe: Thrown in Example.exe
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    
    Unhandled Exception: System.ArgumentException: Thrown in Example.exe
       at Example.Main()
     */
    
    ' This example produces output similar to the following:
    '
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    'ArgumentException caught in Example.exe: Thrown in Example.exe
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    '
    'Unhandled Exception: System.ArgumentException: Thrown in Example.exe
    '   at Example.Main()
    

Menerima Pemberitahuan Pengecualian Kesempatan Pertama di Domain Aplikasi Lain

Jika program Anda berisi lebih dari satu domain aplikasi, Anda dapat memilih domain aplikasi mana yang menerima pemberitahuan.

Untuk menerima pemberitahuan pengecualian kesempatan pertama dalam domain aplikasi yang Anda buat

  1. Tentukan penanganan aktivitas untuk peristiwa FirstChanceException. Contoh ini menggunakan metode static (metode Shared dalam Visual Basic) yang mencetak nama domain aplikasi tempat peristiwa ditangani dan properti Message pengecualian.

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
    
    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
    
  2. Buat domain aplikasi dan tambahkan penanganan aktivitas ke peristiwa FirstChanceException untuk domain aplikasi tersebut. Dalam contoh ini, domain aplikasi bernama AD1.

    AppDomain ad = AppDomain.CreateDomain("AD1");
    ad.FirstChanceException += FirstChanceHandler;
    
    Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
    AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
    

    Anda dapat menangani peristiwa ini di domain aplikasi default dengan cara yang sama. Gunakan properti AppDomain.CurrentDomain (Shared dalam Visual Basic) static di Main() untuk mendapatkan referensi ke domain aplikasi default.

Untuk menunjukkan pemberitahuan pengecualian kesempatan pertama di domain aplikasi

  1. Buat objek Worker di domain aplikasi yang Anda buat di prosedur sebelumnya. Kelas Worker harus bersifat publik, dan harus berasal dari MarshalByRefObject, seperti yang ditunjukkan pada contoh lengkap di akhir artikel ini.

    Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                            typeof(Worker).Assembly.FullName, "Worker");
    
    Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                GetType(Worker).Assembly.FullName, "Worker"),
                            Worker)
    
  2. Panggil metode objek Worker yang memunculkan pengecualian. Dalam contoh ini, metode Thrower dipanggil dua kali. Pertama kali, argumen metode adalah true, yang menyebabkan metode menangkap pengecualiannya sendiri. Kedua kalinya, argumennya adalah false, dan metode Main() menangkap pengecualian di domain aplikasi default.

    // The worker throws an exception and catches it.
    w.Thrower(true);
    
    try
    {
        // The worker throws an exception and doesn't catch it.
        w.Thrower(false);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
    ' The worker throws an exception and catches it.
    w.Thrower(true)
    
    Try
        ' The worker throws an exception and doesn't catch it.
        w.Thrower(false)
    
    Catch ex As ArgumentException
    
        Console.WriteLine("ArgumentException caught in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, ex.Message)
    End Try
    
  3. Tempatkan kode dalam metode Thrower untuk mengontrol apakah metode menangani pengecualiannya sendiri.

    if (catchException)
    {
        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);
    }
    
    If catchException
    
        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
    

Contoh

Contoh berikut membuat domain aplikasi bernama AD1 dan menambahkan penanganan aktivitas ke peristiwa FirstChanceException domain aplikasi. Contoh tersebut membuat instans kelas Worker di domain aplikasi, dan memanggil metode bernama Thrower yang menampilkan ArgumentException. Bergantung pada nilai argumennya, metode menangkap pengecualian atau gagal menanganinya.

Setiap kali metode Thrower menampilkan pengecualian di AD1, peristiwa FirstChanceException dimunculkan di AD1, dan penanganan aktivitas menampilkan pesan. Runtime bahasa umum kemudian mencari penanganan pengecualian. Dalam kasus pertama, penanganan pengecualian ditemukan di AD1. Dalam kasus kedua, pengecualian tidak ditangani di AD1, dan sebagai gantinya ditangkap di domain aplikasi default.

Catatan

Nama domain aplikasi default sama dengan nama yang dapat dieksekusi.

Jika Anda menambahkan penanganan untuk peristiwa FirstChanceException ke domain aplikasi default, peristiwa tersebut akan dimunculkan dan ditangani sebelum domain aplikasi default menangani pengecualian. Untuk melihatnya, tambahkan kode C# AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; (dalam Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) di awal Main().

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

class Example
{
    static void Main()
    {
        // To receive first chance notifications of exceptions in
        // an application domain, handle the FirstChanceException
        // event in that application domain.
        AppDomain ad = AppDomain.CreateDomain("AD1");
        ad.FirstChanceException += FirstChanceHandler;

        // Create a worker object in the application domain.
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                                typeof(Worker).Assembly.FullName, "Worker");

        // The worker throws an exception and catches it.
        w.Thrower(true);

        try
        {
            // The worker throws an exception and doesn't catch it.
            w.Thrower(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
{
    public void Thrower(bool catchException)
    {
        if (catchException)
        {
            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);
        }
    }
}

/* This example produces output similar to the following:

FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in AD1: Thrown in AD1
FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in Example.exe: Thrown in AD1
 */
Imports System.Reflection
Imports System.Runtime.ExceptionServices

Class Example
    Shared Sub Main()

        ' To receive first chance notifications of exceptions in 
        ' an application domain, handle the FirstChanceException
        ' event in that application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
        AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler


        ' Create a worker object in the application domain.
        Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                    GetType(Worker).Assembly.FullName, "Worker"),
                                Worker)

        ' The worker throws an exception and catches it.
        w.Thrower(true)

        Try
            ' The worker throws an exception and doesn't catch it.
            w.Thrower(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

    Public Sub Thrower(ByVal catchException As Boolean)

        If catchException

            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
End Class

' This example produces output similar to the following:
'
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in AD1: Thrown in AD1
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in Example.exe: Thrown in AD1

Lihat juga