Помощник по отладке управляемого кода asynchronousThreadAbort
Примечание.
Эта статья относится к .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздние версии.
Помощник по отладке управляемого кода (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();
}