Cook Computing

Why Does Thread Class Not Support IDisposable?

September 12, 2009 Written by Charles Cook

Thinking about threads in the previous post led to consider why the Thread class doesn't implement IDisposable. After all, there will be unmanaged resources associated with each thread, for example at least a thread handle (there is a distinction between logical and physical threads in .NET but I believe that there is usually a one-one relationship, except perhaps the CLR in SQL Server?). I wrote the following code to determine that at least one handle is associated with each instance of Thread and that it is presumably not closed until the Thread instance is finalized (I used class Foo to prove that the finalizer was being run):


class Program
{
  static void Main(string[] args)
  {
    PerformanceCounter counter = new PerformanceCounter(
      "Process", "Handle Count", "TestThreadDisposable");
    Console.WriteLine("initial: {0}", counter.NextValue());
    for (int i = 0; i < 100; i++)
    {
      new Thread(() => { }).Start();
    }
    Console.WriteLine("before GC: {0}", counter.NextValue());
    new Foo();
    GC.Collect(); // force garbage collection
    Thread.Sleep(4000); // allow finalizer thread to run
    Console.WriteLine("after GC: {0}", counter.NextValue());
  }
 
  class Foo
  {
    ~Foo()
    {
      Console.WriteLine("finalizer running");
    }
  }
}

The results show that a number of handles are associated with each instance of Thread but they are not released when the instance is finalized:


initial: 270
before GC: 811
finalizer running
after GC: 811

So either a reference to the Thread instance is being held internally or the handles are being cached in some other way. Either way it shows that implementing IDisposable would not make any difference, at least in the current implementation of Thread. I increased the number of threads being created and the handle count goes down at some point so there is some mechanism for closing them, as you would expect.

Regardless of this, if your program is creating so many threads that handle count becomes a problem then I guess you would have bigger problems anyway.