I'm sure this has already been pointed out, but I couldn't find it anywhere.
I recently ran into an article by Jon Skeet, C# in Depth - Iterator block implementation details: auto-generated state machine.
He points out that if your iterator has a disposal routine, the auto-generated code contains an empty try block, followed by a finally block. Here is an excerpt from his article.
void IDisposable.Dispose()
{
switch (this.<>1__state)
{
case 1:
case 2:
break;
// Very strange! Reflector bug? See below.
default:
break;
try
{
}
finally
{
this.<>m__Finally6();
}
break;
}
}
This is actually by design. The C# compiler team have done this to ensure that thread aborts don't interrupt the disposal routine. Here is the MSDN documentation on the Thread.Abort method.
"When this method is invoked on a thread, the system throws a ThreadAbortException in the thread to abort it. ThreadAbortException is a special exception that can be caught by application code, but is re-thrown at the end of the catch block unless ResetAbort is called. ResetAbort cancels the request to abort, and prevents the ThreadAbortException from terminating the thread. Unexecuted finally blocks are executed before the thread is aborted."
If you'd like to experiment, this little program demonstrates the behaviour quite nicely.
static void Main(string[] args)
{
var t = new Thread(() =>
{
//try { }
//finally
//{
Thread.Sleep(1000);
Console.WriteLine("finished");
//}
});
t.Start();
Thread.Sleep(1);
t.Abort();
Console.WriteLine("thread aborted");
Console.ReadLine();
}
Enjoy!
By the way. If you don't know the in depth workings of iterator blocks, Jon's article is a great read.
More soon,
James
Comments