Как я могу обнаруживать ThreadAbortException в конце концов блок? (.СЕТЬ)

голоса
8

У меня есть некоторые критические логики в блоке, наконец (с пустым блоком TRY), потому что я хочу, чтобы гарантировать, что код запускается на выполнение даже если поток прерывается. Тем не менее, я хотел бы также обнаружить ThreadAbortException. Я обнаружил, что обертывание моей критическую попытки / окончательно блокировать в Try / улове не поймать ThreadAbortException. Есть ли способ, чтобы обнаружить его?

пытаться {
    пытаться { }
    в конце концов {
        // критическая логика
    }
} Задвижка (Исключение экс) {
    // ThreadAbortException не ловятся здесь, но исключения выброшены
    // внутри критической логики
}
Задан 09/12/2008 в 17:02
источник пользователем
На других языках...                            


7 ответов

голоса
8

Это любопытная проблема.

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

Таким образом, я хотел обнаружить исключение с этим:

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = false;
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

(Мой фактический код просто спал в этой критической секции кода, так что я мог быть уверен, что это будет прервать после этого наконец-то.)

Он напечатал:

Тема прервана? Ложь

Хм, странно!

Так я думал о делать немного больше работы там, чтобы обмануть любую «умную» оптимизацию:

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = AmIEvil();
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

Где AmIEvilэто просто:

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AmIEvil() {
  return false;
}

Наконец он напечатал:

Тема прервана? Правда

И там у вас есть. Используйте это в коде:

try {
  try { }
  finally { /* critical code */ }
  NoOp();
}
catch (Exception ex) {
  // ThreadAbortException is caught here now!
}

Где NoOpэто просто:

[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
Ответил 03/03/2011 в 19:02
источник пользователем

голоса
3

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

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

ThreadAbortException

Ответил 09/12/2008 в 17:07
источник пользователем

голоса
2

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

Ответил 18/11/2011 в 22:23
источник пользователем

голоса
2

Я не думаю, что это возможно.

Зачем вам нужно обрабатывать ThreadAbortException в первую очередь? Вызов Thread.Abort () , как правило , является признаком плохого дизайна. Есть переменную флагу , что при установке истины будет просто вернуться; из функции потока, после соответствующей очистки, конечно.

Таким образом, вам не нужно будет беспокоиться о том, за исключением.

Ответил 09/12/2008 в 17:22
источник пользователем

голоса
2

Читайте о стесненном Execution регионов .

В частности, метод RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup будет полезно здесь.

Ответил 09/12/2008 в 17:04
источник пользователем

голоса
0

Пытались ли вы что-нибудь подобное?

try {
    try { }
    catch (ThreadAbortException)
    {
      ThreadAbortExceptionBool = true;
    }
    finally {
        // critical logic
        if (ThreadAbortExceptionBool)
          // Whatever
    }
} 
catch(Exception ex) {
    // ThreadAbortException is not caught here, but exceptions thrown
    // from within the critical logic are
}
Ответил 02/03/2009 в 16:15
источник пользователем

голоса
0

Я согласен с Arul. Вызов Thread.Abort () является признаком плохого дизайна.

Процитирую Питер Ритчи из MSDN: Thread.Abort (курсив мой):

Там же много причин, чтобы не использовать Thread.Abort и ThreadAbortException

На некоторых платформах (например, x64 и IA64) по прекращению может произойти до Monitor.Enter и попробовать блок (даже с замком / SyncLock), в результате чего монитор сироту. ThreadAbortException может произойти в 3-й код партии не написан для обработки потоков Прервать. Поток может быть прерван во время обработки, наконец, блок в .NET 1.x Использование исключений для нормальной логики потока управления. Асинхронное исключение может прервать модификацию состояния шарда или ресурсы, оставляя их повредиться.

Более подробно см:
http://msmvps.com/blogs/peterritchie/archive/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program.aspx
HTTP: // www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx

Ответил 11/12/2008 в 11:43
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more