Friday, November 26, 2010

Why Thread.Abort() is NOT evil

I apply the using statement quite a lot:
using(FileStream fs = new FileStream(path, mode)) {
//Do work on fs here
}


This is a syntactic sugar for the try/finally construct, eg:
FileStream fs = null;
try {
fs = new FileStream(path, mode);
//Do work on fs here
}finally{
if(fs != null)
fs.Dispose();
}


Today I was researching the java.thread.stop() method, which is deprecated because it is unsafe.

While doing so, I found multiple post stating that the same is true for .Net applications. They all seem to refer to the article "How To Stop a Thread in .NET (and Why Thread.Abort is Evil)", which claims that the exception can occur in the finally block.

Fortunately this is NOT true, but I just had to make sure:
static volatile bool done = false;
static volatile bool inFinally = false;
static void Main()
{
Thread t = new Thread(new ThreadStart(RunThread));
t.Start();

//Wait for the thread to enter the finally block
while (!inFinally)
Thread.Sleep(100);

//Abort the thread in the finally block
t.Abort();

//Provoke it by issuing a double abort exception
Thread.Sleep(100);
t.Abort();

//Now make sure the thread is done
t.Join();

//Present the results
if (!done)
Console.WriteLine("Thread.Abort() is unsafe!");
else
Console.WriteLine("Thread.Abort() is NOT evil!");
}

//An emulated thread
private static void RunThread()
{
int x = 0;
try { x = 1000; } //A harmless operation
finally
{
//Flag that we are ready for the exception
inFinally = true;
//Do some time consuming work to ensure that we
// stay in the finally block for a while
for (int i = 0; i < 10000; i++)
for (int j = 0; j < 10000; j++)
x++;

//If we did not get interrupted, set the flag
done = true;
}
}


And fortunately the output is:
Thread.Abort() is NOT evil!

No comments: