W jaki sposób można wykryć ThreadAbortException w bloku finally? (.NETTO)

głosy
8

Mam pewne krytyczne logiki w bloku finally (z pustym bloku try), ponieważ chcę, aby zagwarantować, że kod zostanie wykonany nawet jeśli wątek jest przerywana. Jednak Chciałbym również, aby wykryć ThreadAbortException. Odkryłam, że owijając moje krytyczne try / finally zablokować w try / catch nie złapać ThreadAbortException. Czy istnieje jakiś sposób, aby go wykryć?

próbować {
    próbować { }
    Wreszcie {
        // logika krytyczny
    }
} Zaczep (wyjątek ex) {
    // ThreadAbortException nie zostanie złapany tutaj, ale wyjątki wyrzucane
    // z poziomu krytycznego logiki
}
Utwórz 09/12/2008 o 17:02
źródło użytkownik
W innych językach...                            


7 odpowiedzi

głosy
8

Jest to ciekawy problem.

Kod, który pisał powinno działać. Wydaje się, że to jakiś rodzaj optymalizacji dzieje, że nie zdecyduje się zadzwonić do obsługi catch.

Tak, chciałem, aby wykryć wyjątek z tego:

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

(Mój rzeczywisty kod prostu spał w tej krytycznej sekcji kodu, więc mogę być pewien, że w końcu przerwać po tym).

To drukowane:

Wątek przerwany? Fałszywy

Hmmm, dziwne, rzeczywiście!

Więc pomyślałem o zrobieniu trochę więcej pracy tam, aby oszukać żadnych „inteligentnych” optymalizacje:

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

Gdzie AmIEviljest tylko:

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

Wreszcie drukowane:

Wątek przerwany? Prawdziwe

I tam masz. Użyj tego w kodzie:

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

Gdzie NoOpjest tylko:

[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
Odpowiedział 03/03/2011 o 19:02
źródło użytkownik

głosy
3

rzeczywiście można wykonać kod w instrukcji catch dobrze dla ThreadAbortException. Problemem jest to, że wyjątek zostanie rethrown raz wykonanie pozostawia bloku catch.

Jeśli chcesz faktycznie zatrzymać wyjątek od kontynuowania można nazwać Thread.ResetAbort (). To wymaga pełnego zaufania i choć chyba że masz konkretny scenariusz, to prawie na pewno coś złego zrobić.

ThreadAbortException

Odpowiedział 09/12/2008 o 17:07
źródło użytkownik

głosy
2

Jeśli wywołanie Thread.Abort jest zła konstrukcja dlaczego SQL Server nazwać go na wątku, który jest uruchomiony kod użytkownika? Bo to jest dokładnie, jak anulować zapytanie jest obsługiwane i powoduje koszmary.

Odpowiedział 18/11/2011 o 22:23
źródło użytkownik

głosy
2

Nie sądzę, że jest to możliwe.

Dlaczego trzeba obsłużyć ThreadAbortException w pierwszej kolejności? Wywołanie Thread.Abort () jest zwykle oznaką złej konstrukcji. Mają zmienną flagi, że gdy wartość true po prostu powrotu; od funkcji nici po odpowiednim oczyszczania oczywiście.

W ten sposób nie trzeba się martwić o wyjątku.

Odpowiedział 09/12/2008 o 17:22
źródło użytkownik

głosy
2

Przeczytaj o ograniczonych Regionów Execution .

W szczególności, metoda RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup będzie tu przydatny.

Odpowiedział 09/12/2008 o 17:04
źródło użytkownik

głosy
0

Czy próbowałeś coś takiego?

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
}
Odpowiedział 02/03/2009 o 16:15
źródło użytkownik

głosy
0

Zgadzam się z Arul. Wywołanie Thread.Abort () jest oznaką złej konstrukcji.

Pozwolę sobie zacytować Peter Ritchie z MSDN: Thread.Abort (podkreślenie moje):

Istnieje wiele powodów, aby nie używać Thread.Abort i ThreadAbortException

Na niektórych platformach (jak x64 i IA64) Do przerwania może nastąpić przed Monitor.Enter i bloku try (nawet z zamkiem / SyncLock), pozostawiając monitor osieroconego. ThreadAbortException może występować w 3 kodzie strony nie jest napisane, aby obsłużyć przerwanie nici. Gwint może być przerwane podczas przetwarzania w końcu zablokować w NET 1.x Zastosowanie wyjątków dla normalnego przepływu logiki sterowania. Asynchroniczny Wyjątkiem może przerwać modyfikację stanu Shard lub zasobów, pozostawiając ich uszkodzeniu.

Więcej szczegółów na stronie:
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

Odpowiedział 11/12/2008 o 11:43
źródło użytkownik

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