Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
970 views
in Technique[技术] by (71.8m points)

multithreading - How can I detect a ThreadAbortException in a finally block? (.NET)

I have some critical logic in a finally block (with an empty try block), because I want to guarantee that the code gets executed even if the thread is aborted. However, I'd also like to detect the ThreadAbortException. I've found that wrapping my critical try/finally block in a try/catch does not catch the ThreadAbortException. Is there any way to detect it?

try {
    try { }
    finally {
        // critical logic
    }
} catch(Exception ex) {
    // ThreadAbortException is not caught here, but exceptions thrown
    // from within the critical logic are
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is a curious problem.

The code you posted should work. It seems there's some kind of optimization going on that decides not to call your catch handler.

So, I wanted to detect the exception with this:

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

(My actual code just slept in that critical code section, so I could be sure it would abort after that finally.)

It printed:

Thread aborted? False

Hmmm, strange indeed!

So I thought about doing a little bit more work there, to trick any "smart" optimizations:

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

Where AmIEvil is just:

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

Finally it printed:

Thread aborted? True

And there you have it. Use this in your code:

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

Where NoOp is just:

[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...