Daisy said:
don't.
Righto. But how *would* you overcome something like this? Say you wanted to
read a property from an object you're not sure still exists. You test it
exists first, but you've still got a race condition. Wrapping it in a try
block would work, but is that the best way?
--
If you have a reference to an object then the object will be around so long
as you hang onto the reference. The issue is not whether the memory is still
valid or not - as long as the reference is rooted the memory is still
valid - the original issue is one of race conditions between threads.
A try block does not help prevent race conditions, it only catches an
exception that is thrown in the guarded block of code. The only way to
prevent race conditions is to use synchronization mechanisms; the code
snippet shown does absolutely nothing in this regard.
Further, the entire premise of the code snippet shown is incorrect. There
are many side-effects to inducing an abort exception asynchronously in
another thread, all of them bad. For example, the target thread may be
executing code in a finally block - this can be interrupted with unknown
consequences. Another is that if the exception occurs while the target
thread is executing code in a static constructor the type is rendered
unusable in that appdomain.
In addition thread objects continue to exist for some time even after the
thread is no longer "alive" (holding a reference to the thread will do
this), and if you call abort on a thread that is already terminated the
request is ignored, so I still am mystified as to why the author of that
article thought it necessary to call IsAlive prior to calling Abort.
In the snippet...
if ( t.IsAlive )
t.Abort();
The amount of time that can elapse after calling IsAlive and before
Thread.Abort is executed is unbounded. The call to IsAlive can indicate the
target thread is alive but before the next line of code executes a context
switch can occur, other code executes, and the target thread could actually
die. Even if the thread is still alive the amount of time it takes for the
thread to actually terminate is also unbounded.
One safe way for one thread to signal another thread to terminate is to use
a signalling mechanism, such as a ManualResetEvent, that the calling thread
sets to the signalled state and the target threads periodically checks. This
is a synchronous mechanism that allows the target thread to reach a known
safe point in its execution path before it terminates. This is a relatively
standard technique. If you need to know when the thread has terminated you
can wait on the thread object to become signalled (do a Join on the thread
object).
Dave