I’ve always been a big fan of using the ThreadPool for asynchronous execution, but in ASP.NET it is not the best approach for multi-threading. I’m not writing about when threading is appropriate and the impact of multi-core or dual core machines when doing threading, but point out that the ThreadPool is not the best choice for ASP.NET applications.

ThreadPool is easy

The reason why I like the ThreadPool is because it is managed for me and it is very easy to use and it only takes one line of code to execute a method in a new thread by using the QueueUserWorkItem method.

System.Threading.ThreadPool.QueueUserWorkItem(SomeMethod);

Private void SomeMethod(object stateInfo)
{
    // Execute something...
}

You can also send a parameter easily like so:

System.Threading.ThreadPool.QueueUserWorkItem(SomeMethod, variable);

That variable then gets transferred to the stateInfo parameter of SomeMethod where you can then cast it from object to whatever data type it is.

Private void SomeMethod(object stateInfo)
{
    int number = (int)stateInfo;
    // Execute something...
}

The ThreadPool in ASP.NET

You can use the ThreadPool in exactly the same way in ASP.NET and it works just as you would expect. The problem is not in the ThreadPool itself but in what else ASP.NET uses it for at the same time. ASP.NET is multi-threaded by design and it uses the ThreadPool to serve pages and content mapped to the ASP.NET ISAPI filter.

If you also use the ThreadPool, then ASP.NET has fewer threads to utilize and requests are put on hold until the pool returns a free thread. This might not be a problem for a low traffic site, but more popular sites can get into trouble. Low traffic sites can get into trouble if they use the ThreadPool a lot.

Don’t use it

Whether you work on a low or high traffic site, there really is no reason to use the ThreadPool when you can create new threads almost as easily that doesn’t disturb the pool. Here is an example that uses an anonymous method as a delegate:

System.Threading.ThreadStart threadStart = delegate { SomeMethod(variable); };
System.Threading.Thread thread = new System.Threading.Thread(threadStart);
thread.IsBackground = true;
thread.Start();

That’s four lines instead of one, but that’s a low price to pay. You could always create a helper method to call whenever you want to start a new thread.

public static void StartBackgroundThread(ThreadStart threadStart)
{
  if (threadStart != null)
  {
    Thread thread = new Thread(threadStart);
    thread.IsBackground = true;
    thread.Start();
  }
}

Then just call it in one line like so:

StartBackgroundThread(delegate { SomeMethod(variable); });

Word of caution

The ThreadPool is managed by the CLR, which provide a level of control that a normal thread doesn’t get. By using an un-pooled thread you also have the ability to do much more harm if you don’t know what you are doing.

You have the ability to stop the AppPool from being recycled and the application from being stopped if you aren’t careful. For instance, if you set the IsBackground property to false, it will exist in the foreground and can make it difficult for the application to recycle or restart. However, the example shown above is not doing that, so don’t worry about damaging your application by using it.

Comments


Comments are closed