The empty try block mystery

Posted on April 10, 2008

22


Problem:

I had used .NET Mass Downloader tool to download .NET 2.0 Framework sourcecode some time ago. While reading Timer.cs (System.Windows.Forms.Timer) and a couple of other classes I noticed something interesting.

Does the following piece of code look odd to you? Notice the empty “try” block and all processing being done in the “finally” block.

public void Foo()
{
try
{
}
finally
{
DoSomething();
DoSomethingElse();
}
}

It’s (most likely, you’d think – right?) not the work of a programmer misunderstanding what was asked of him :)

Solution:

This methodology guards against a Thread.Abort call interrupting the processing. The MSDN page of Thread.Abort says that “Unexecuted finally blocks are executed before the thread is aborted”. So in order to guarantee that your processing finishes even if your thread is aborted in the middle by someone calling Abort on your thread, you can place all your code in the finally block (the alternative is to write code in the “catch” block to determine where you were before “try” was interrupted by Abort and proceed from there if you want to).

But what if your thread is aborted while code in the finally block is executing?

Again, here’s what the MSDN page says:

In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.

That’s bad because this behavior could potentially cause leakage of resources if you have your code for freeing up resources written in the “finally” block and it got interrupted in the middle by a call to Abort.

What about .NET 2.0:

I wrote a simple program to check the behavior and on my machine running .NET 2.0 on Vista Enterprise edition, finally block isn’t interrupted even if an Abort call is made on the thread running the “finally” block.

The Code:

I had a function named LaunchThread to start the thread. This function was called from the handler for the “Load” event of the form.

private Thread mThread;

public void LaunchThread()
{
this.mThread = new Thread(ThreadMain);
this.mThread.Start();
}

I had a button on my form. I had a handler for its Click event which basically called Abort on the thread.

private void button1_Click(object sender, EventArgs e)
{
if (this.mThread != null && this.mThread.IsAlive)
{
this.mThread.Abort();
this.mThread.Join();
MessageBox.Show(“Thread Aborted”);
}
else
{
MessageBox.Show(“Thread already died”);
}
}

This is what ThreadMain looked like:

public void ThreadMain()
{
try
{
}
finally
{
MessageBox.Show(“Going to sleep!”);
Thread.Sleep(10000);
MessageBox.Show(“Just finished sleeping!”);
}
}

To test the application, I ran the application, waited a couple of seconds and then clicked on the button. Here is the sequence of messages that appeared:

  • As soon as the form was launched – “Going to sleep!
  • No messages appeared in response to me clicking on the button.
  • After 10 seconds – “Just finished sleeping!”
  • And immediately after that – “Thread Aborted”

Since no message appeared in response to me clicking on the button, it is clear that Thread.Sleep call in the “finally” block was not interrupted by Abort.

Changing ThreadMain like the following, leads to different results:

public void ThreadMain()
{
try
{
MessageBox.Show(“Going to sleep!”);
Thread.Sleep(10000);
MessageBox.Show(“Just finished sleeping!”);
}
finally
{
}
}

In this case, when I clicked on the button, Thread.Sleep call was interrupted by the call to Abort as I saw the following messages:

  • As soon as the form was launched – “Going to sleep!”
  • Just after clicking on the button “Thread aborted”
About these ads
Tagged: , ,
Posted in: .NET, General