Поделиться через


Помощник по отладке управляемого кода asynchronousThreadAbort

Обновлен: Ноябрь 2007

Помощник по отладке управляемого кода (MDA) asynchronousThreadAbort активируется в том случае, если поток пытается выполнить асинхронное аварийное завершение работы в другом потоке. В случае синхронного завершения работы потока, помощник по отладке управляемого кода asynchronousThreadAbort не активируется.

Признаки

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

Операции, которые предполагаются атомарными, скорее всего, были прерваны, завершившись частично, в результате чего данные приложения находятся в непредсказуемом состоянии. Исключение ThreadAbortException может возникать в произвольных точках выполнения кода, зачастую в тех местах, где исключение появляться не должно. Возможно, код не сможет обработать такое исключение, что приводит к повреждению состояния.

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

Причина

Код в одном потоке вызвал метод Thread.Abort в целевом потоке, чтобы выполнить асинхронное аварийное завершение работы потока. Аварийное завершение работы потока является асинхронным, поскольку код, вызвавший метод Abort, выполняется в потоке, отличном от целевого потока. Синхронное аварийное завершение работы не является проблемой, поскольку работа потока, в котором выполняется метод Abort, была завершена в безопасной контрольной точке с согласованным состоянием приложения.

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

Вызовы в неуправляемом коде и блоках finally не будут завершаться в аварийном режиме асинхронно, а непосредственно после выхода из одной из этих категорий.

Причину этого сложно определить вследствие случайного характера данной проблемы.

Решение

Следует избегать разработки кода, который требует использования асинхронного аварийного завершения работы потока. Существует несколько приемов прерывания работы целевого потока, которые не требуют вызова метода Abort. Безопаснее всего применить определенный механизм, например общее свойство, которое дает целевому потоку команду на запрос прерывания. Целевой поток проверяет команду в определенных безопасных контрольных точках. Если запрос на прерывание обнаружен, работа потока корректно завершается.

Влияние на среду выполнения

Данный помощник по отладке управляемого кода не оказывает влияния на среду CLR. Он только сообщает сведения об асинхронных аварийных завершениях работы потока.

Результат

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

Конфигурация

<mdaConfig>
  <assistants>
    <asynchronousThreadAbort />
  </assistants>
</mdaConfig>

Пример

Для активации помощника по отладке управляемого кода asynchronousThreadAbort требуется только вызов метода Abort в отдельном работающем потоке. Следует учитывать последствия в случае, если содержимое функции запуска потока настроено для выполнения более сложных операций, которые могут аварийно прерываться в любой произвольной точке.

using System.Threading;
void FireMda()
{
    Thread t = new Thread(delegate() { Thread.Sleep(1000); });
    t.Start();
    // The following line activates the MDA.
    t.Abort(); 
    t.Join();
}

См. также

Основные понятия

Диагностика ошибок посредством управляемых помощников по отладке

Ссылки

Thread