Как обрабатывать AppDomain.Unload и связанные с ним ThreadAbortException - PullRequest
2 голосов
/ 23 февраля 2012

Согласно MSDN, AppDomain.Unload заставляет все потоки внутри выгружаемого AppDomain генерировать исключение прерывания потока.

Потоки в домене завершаются с помощью метода Abort, который создает исключение ThreadAbortException в потоке. Хотя нить должен завершиться быстро, он может продолжить выполнение для непредсказуемое количество времени в конечном пункте. - от MSDN

Таким образом, я понимаю, что каждый раз, когда я пишу код в любом месте, которое, как ожидается, будет выполняться в этом домене приложений, я должен ожидать, что прерывание потока может произойти в любом потоке в любое время. Это правда? Должен ли весь код везде предполагать, что исключение ThreadAbortException может быть выдано в любое время?

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

Есть ли другие соображения, которые необходимо принять, чтобы избежать ненужной обработки исключений / регистрации ошибок?

Ответы [ 2 ]

5 голосов
/ 23 февраля 2012

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

Наконец, вы должны знать, что вы можете ловить TAE и выполнять компенсационный код в блоке catch. Единственное, что в них особенного, это то, что они будут немедленно переброшены после блока захвата, так что вы не сможете их «проглотить». Вы можете подавить их, используя Thread.ResetAbort(), но в этом случае это, вероятно, нежелательный эффект.

Мы все написали такой код:

public void Foo() {
    try {
        Do.Some.Stuff();
    } catch (Exception ex) {
       Console.Out.WriteLine("Oh noes!");
    }
}

И да, блок catch будет перехватывать все 1 , включая TAE и OOM.

Здесь следует иметь в виду, что за всеми вышеперечисленными исключениями мир в основном заканчивается. Все, что вас должно волновать, - это то, что любые важные для транзакций данные, с которыми вы имеете дело, не будут потеряны или оставлены в плохом состоянии, и именно поэтому мы обычно оставляем такие вещи, как транзакционно-безопасный ввод / вывод, умным людям в Microsoft и Oracle. кто пишет базы данных. Если ваш код выполняет, например, ввод / вывод с использованием плоских файлов, который вы должны быть действительно уверены, что никогда не оставит файл в плохом состоянии, то вы должны думать о режимах отказа очень целостным образом. например, «что произойдет, если питание отключится, когда этот файл наполовину записан?»

1 Единственное исключение состоит в том, что Исключения StackOverflow обычно не могут быть перехвачены . Это было изменение в .NET 2.0.

1 голос
/ 23 февраля 2012

Вы не можете обработать ThreadAbortException, поэтому нет необходимости перехватывать исключение.Более технически

- это специальное исключение, при котором может быть перехвачено, но оно будет автоматически поднято снова в конце блока перехвата

С здесь .

...