AppDomain.FirstChanceException Событие

Определение

Происходит при создании исключения в управляемом коде, перед тем как среда выполнения ищет стек вызовов для обработчика исключений в домене приложений.

C#
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>? FirstChanceException;
C#
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
C#
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;

Тип события

Атрибуты

Примеры

В следующем примере создается ряд доменов приложений с именем AD0 через AD3с Worker объектом в каждом домене приложения. Каждый Worker объект имеет ссылку Worker на объект в следующем домене Worker приложения, за исключением в последнем домене приложения. Событие FirstChanceException обрабатывается во всех доменах приложений, кроме AD1.

Примечание

Помимо этого примера, в котором демонстрируются уведомления об исключениях в первую очередь в нескольких доменах приложений, простые варианты использования можно найти в разделе Практическое руководство. Получение уведомлений об исключениях First-Chance.

После создания доменов приложения домен приложения по умолчанию вызывает TestException метод для первого домена приложения. Каждый Worker объект вызывает TestException метод для следующего домена приложения, пока последний Worker не вызовет исключение, которое обрабатывается или необработано. Таким образом, текущий поток проходит через все домены приложений и TestException добавляется в стек в каждом домене приложения.

Когда последний Worker объект обрабатывает исключение, FirstChanceException событие вызывается только в последнем домене приложения. Другие домены приложений никогда не получают возможность обработать исключение, поэтому событие не вызывается.

Если последний Worker объект не обрабатывает исключение, FirstChanceException событие вызывается в каждом домене приложения, который имеет обработчик событий. После завершения каждого обработчика событий стек продолжает раскрутку, пока исключение не будет перехвачено доменом приложения по умолчанию.

Примечание

Чтобы увидеть, как увеличивается отображение стека по мере приближения события к домену приложения по умолчанию, измените e.Exception.MessageFirstChanceHandler на e.Exception в обработчиках событий. Обратите внимание, что при TestException вызове через границы домена приложения он отображается дважды: один раз для прокси-сервера и один раз для заглушки.

C#
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
 */

Комментарии

Это событие является только уведомлением. Обработка этого события не обрабатывает исключение и никак не влияет на последующую обработку исключений. После вызова события и вызова обработчиков событий среда CLR начинает поиск обработчика исключения. FirstChanceException предоставляет домену приложения первую возможность проверить любое управляемое исключение.

Событие может обрабатываться для каждого домена приложения. Если поток проходит через несколько доменов приложений при выполнении вызова, событие вызывается в каждом домене приложения, который зарегистрировал обработчик событий, прежде чем среда CLR начнет поиск соответствующего обработчика исключений в этом домене приложения. После обработки события выполняется поиск соответствующего обработчика исключений в этом домене приложения. Если ни один из них не найден, событие вызывается в следующем домене приложения.

Необходимо обработать все исключения, возникающие в обработчике событий для FirstChanceException события. В противном FirstChanceException случае вызывается рекурсивно. Это может привести к переполнению стека и завершению работы приложения. Рекомендуется реализовать обработчики событий для этого события в качестве регионов ограниченного выполнения (CER), чтобы во время обработки уведомлений об исключении, связанные с инфраструктурой, такие как нехватка памяти или переполнение стека, не влияли на виртуальную машину.

Это событие не вызывается для исключений, указывающих на повреждение состояния процесса, таких как нарушения доступа, если обработчик событий не является критически важным для безопасности и не имеет HandleProcessCorruptedStateExceptionsAttribute атрибута .

Среда CLR приостанавливает прерывания потока во время обработки этого события уведомления.

Применяется к

Продукт Версии
.NET Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

См. также раздел