Ian Griffiths has just made
a very good
post about the evils of Thread.Abort.
Since Ian doesn't have comments on his blog (thats what happens when you write
your own blog engine ;-) ) I'll post here to pick him up on one thing.
Ian talks about the problems with Thread.Abort
very lucidly and says that using a volatile bool
flag is a much better solution and people shouldn't get hung up about the fact
the thread won't terminate there and then. The one proviso, is
that the thread has to be able to check the flag to know it has to bring itself
down in an orderly fashion. What if it can't check the flag's
value (notice I say can't rather than doesn't here)? When
would this occur? When the thread is waiting on a synchronization primitive, a
ManualResetEvent for example. In this situation you have to resort
to Thread.Interrupt which, as Ian says, doesn't
raise an asynchronous exception but it will throw a ThreadInterruptedException
if the thread is in a SleepWaitJoin state. This
means if the thread as called Thread.Sleep,
Thread.Join or is waiting on a synchronization primitive it will be
"woken up". When used in conjunction with a volatile bool
flag it makes for a very robust solution.
using System;
using System.IO;
using System.Threading;
class App
{
static volatile bool terminate = false;
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(Func));
t.Start();
Console.ReadLine();
// set the flag to get the thread to come down cleanly
terminate = true;
if( !t.Join(2000) ) // if the thread has taken more than 2 seconds to terminate
{
// Wake the thread up
t.Interrupt();
// wait for it to terminate
t.Join();
}
}
static void Func()
{
// open some resource that requires clean up
using(FileStream fs = File.OpenWrite(@"C:\foo.txt"))
{
// check the flag
while(!terminate)
{
// use the resource
fs.WriteByte(0);
// oh dear, we aren't going to notice the flag for 10 seconds now
Thread.Sleep(10000);
}
}
}
}