Что не так с использованием Thread.Abort()

Так что я знаю, что вы не должны использовать

Thread.Abort()

Но мне никогда не давали хорошее объяснение. Есть ли потеря производительности или какая-то скрытая ошибка?

Я знаю, что вы не можете игнорировать / проглотить исключение ThreadAbortException (что имеет смысл)

7 ответов

Решение

В дополнение ко всем другим хорошим ответам здесь, позвольте мне добавить, что нет никакой гарантии, что вызов Thread.Abort фактически прервет рассматриваемый поток, когда-либо. Возможно (хотя и не особенно легко) "затвердеть" нить от прерывания. Если, например, вы прерываете поток, потому что считаете, что он выполняет враждебный код, тогда враждебный код может противостоять самому разрушению.

Если у вас есть длительная операция с кодом, которой вы не владеете, и которую нужно аккуратно удалить, правильный способ сделать это - поместить этот код в свой собственный процесс, а не в собственный поток. (И предпочтительно в домене приложений с высоким уровнем безопасности в этом процессе.) Затем вы можете просто убить процесс.

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

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

Поток мог взять блокировку и быть в процессе изменения некоторого общего состояния, а Thread.Abort отменит блокировку и оставит общее состояние поврежденным.

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

Monitor.Enter(obj);
// some code - if exception is raised here, then the lock isn't released
Monitor.Exit(obj)

IDisposable someCriticalResource = GetResource();
// some code - if exception is raised here, then the object isn't disposed
someCriticalResource.Dispose();

Кроме того, если вы работаете со многими людьми в команде, если у вас нет хороших обзоров кода, вы не можете гарантировать качество кода, с которым будете работать. Следовательно, хорошая идея - проповедовать "no Thread.Abort()", чем заставлять людей помнить о написании кода, который был бы устойчив к исключениям, возникающим в любом месте этого кода.

Короче. Любой объект IDisposable не может быть уничтожен. Любой заблокированный объект не может быть разблокирован. Все, что должно быть выполнено на 100%, никогда не будет выполнено.

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

Thread.Abort останавливает вашу тему неконтролируемым образом. thread.Abort сгенерирует исключение, которое приведет к немедленной остановке вашего потока.

Что не так с этим: в большинстве случаев вы хотите аккуратно прекратить операцию, которую вы выполняете. Например, если вы выполняете операцию ACID, вам может потребоваться завершить текущую операцию до завершения потока, чтобы ваша система оставалась в стабильном состоянии.

Thread.Abort вызывает исключение в целевом потоке. Тем временем целевой поток может выполнять некоторые критические операции, и возникновение исключения может нарушить состояние вашего приложения.

Другие вопросы по тегам