(Post 16/10/2007) Interrupting a thread arbitrarily
is dangerous, however, because any framework or third-party methods in
the calling stack could unexpectedly receive the interrupt rather than
your intended code. All it would take is for the thread to block briefly
on a simple lock or synchronization resource, and any pending interruption
would kick in. If the method wasn't designed to be interrupted (with appropriate
cleanup code in finally blocks) objects could be left in an unusable state,
or resources incompletely released.
A blocked thread can be released prematurely in one of
two ways:
- via Thread.Interrupt
- via Thread.Abort
This must happen via the activities of another thread;
the waiting thread is powerless to do anything in its blocked state.
Interrupt
Calling Interrupt on a blocked thread forcibly releases
it, throwing a ThreadInterruptedException, as follows:
class Program {
static void Main() {
Thread t = new Thread (delegate() {
try {
Thread.Sleep (Timeout.Infinite);
}
catch (ThreadInterruptedException) {
Console.Write ("Forcibly ");
}
Console.WriteLine ("Woken!");
});
t.Start();
t.Interrupt();
}
}
Interrupting a thread only releases it from its current
(or next) wait: it does not cause the thread to end (unless, of course,
the ThreadInterruptedException is unhandled!)
If Interrupt is called on a thread that’s not blocked,
the thread continues executing until it next blocks, at which point a
ThreadInterruptedException is thrown. This avoids the need for the following
test:
if ((worker.ThreadState &
ThreadState.WaitSleepJoin) > 0)
worker.Interrupt();
which is not thread-safe
because of the possibility of being preempted in between the if statement
and worker.Interrupt.
Interrupting a thread arbitrarily is dangerous, however,
because any framework or third-party methods in the calling stack could
unexpectedly receive the interrupt rather than your intended code. All
it would take is for the thread to block briefly on a simple lock or synchronization
resource, and any pending interruption would kick in. If the method wasn't
designed to be interrupted (with appropriate cleanup code in finally blocks)
objects could be left in an unusable state, or resources incompletely
released.
Interrupting a thread is safe when you know exactly where
the thread is. Later we cover signaling constructs,
which provide just such a means.
Abort
A blocked thread can also be forcibly released via its
Abort method. This has an effect similar to calling Interrupt, except
that a ThreadAbortException is thrown instead of a ThreadInterruptedException.
Furthermore, the exception will be re-thrown at the end of the catch block
(in an attempt to terminate the thread for good) unless Thread.ResetAbort
is called within the catch block. In the interim, the thread has a ThreadState
of AbortRequested.
The big difference, though, between Interrupt and Abort,
is what happens when it's called on a thread that is not blocked. While
Interrupt waits until the thread next blocks before doing anything, Abort
throws an exception on the thread right where it's executing – maybe not
even in your code. Aborting a non-blocked thread can have significant
consequences, the details of which are explored in the later section "Aborting
Threads".
(Sưu tầm) |