Используйте AppDomain.UnhandledException в модульном приложении форм - PullRequest
4 голосов
/ 25 апреля 2011

В настоящее время я разрабатываю полностью модульное приложение .NET, в котором:

  1. Существует приложение хоста, которое загружает DDL-модули.У модулей DDL есть формы, которые можно открывать несколько раз.
  2. Вы можете выгрузить домен приложения.Это приведет к тому, что все открытые формы модуля будут закрыты.

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

Я попытался использовать событие AppDomain.UnhandledException, которому сразу после создания домена AppDomain был назначен обработчик, как показано ниже:

        // Creates the ApplicationDomain
        this._applicationDomain = AppDomain.CreateDomain(this.AppDomainName);
        this._applicationDomain.UnhandledException += new UnhandledExceptionEventHandler(_applicationDomain_UnhandledException);

Проблема в том, что обработчик никогда не вызывается.Microsoft говорит здесь , что

Например, предположим, что поток запускается в домене приложения "AD1", вызывает метод в домене приложения "AD2" и оттуда вызывает метод вДомен приложения "AD3", где он выдает исключение.Первым доменом приложения, в котором может быть вызвано событие UnhandledException, является «AD1».Если этот домен приложения не является доменом приложения по умолчанию, событие также может быть вызвано в домене приложения по умолчанию.

Даже после того, как я назначил обработчик, исключение по-прежнему переходит в

Application.Run (new HostForm ());

Я полагаю, что если бы я создал новый цикл сообщений для формы каждого модуля, он бы работал, потому что тогда поток, в котором будет выполняться форма, будет разделеннить, но это, кажется, глупое решение.

Другая идея, которую я имел, состояла в том, чтобы использовать, кроме события AppDomain.UnhandledException домена приложения по умолчанию, но как я могу тогда:

  1. Откройте для себя AppDomain происхождения и, следовательно, модуль для выгрузки?
  2. Предотвратить смерть приложения?(Я попытался сделать это, и e.IsTerminating имеет истинное значение, и исключение все еще сохраняется в

Кто-нибудь? Пожалуйста, мне действительно это нужно.

1 Ответ

0 голосов
/ 20 апреля 2015

Существует довольно хорошее объяснение (с поддержкой ссылок) о том, почему обработчик AppDomain.CurrentDomain.UnhandledException не подавляет необработанные исключения здесь . Статья MSDN, на которую вы ссылаетесь, также описывает это поведение чуть ниже той части, которую вы цитировали.

В .NET Framework версий 1.0 и 1.1, необработанное исключение что происходит в потоке, отличном от основного потока приложения пойман во время выполнения и, следовательно, не вызывает приложение прекратить. Таким образом, событие UnhandledException может быть поднят без прекращения приложения. Начиная с .NET Framework версии 2.0, этот backstop для необработанных исключений в child темы были удалены, потому что совокупный эффект такого молчания сбои включали снижение производительности, повреждение данных и блокировки, которые трудно было отладить.

Таким образом, даже если бы вы могли инициировать событие, вряд ли вы удовлетворите ваше требование, чтобы приложение не было закрыто вскоре после этого. Обработчик UnhandledException действительно только для того, чтобы дать вам последний шанс записать важную информацию до того, как приложение будет остановлено.

Наиболее устойчивые приложения (например, Google Chrome) будут использовать полную изоляцию процесса, чтобы гарантировать, что все, что пойдет не так в плагине, разрушит внешний хост плагина, а не основное приложение. Я сам использовал этот механизм для создания приложения, аналогичного тому, которое вы описали, и даже дошел до степени создания изолированного AppDomain внутри каждого внешнего хоста плагинов, чтобы гарантировать, что плагины не смогут удалять критические файлы, если основное приложение было поднято.

Есть действительно хорошая статья здесь , которая подробно описывает методы изоляции и повторяет, что система плагинов AppDomain не лучший вариант из-за проблемы UnhandledException. Если вы серьезно относитесь к отказоустойчивой архитектуре подключаемых модулей, я рекомендую реализовать полную изоляцию процессов, как описано в этой последней статье.

...