Use ThreadPool.QueueUserWorkItem With Anonymous Types
I recently had a method in a WinForms application that I wanted to run on a different thread to free up the main UI thread. In .NET 2.0, there exists a simple method to run a method on another thread — ThreadPool.QueueUserWorkItem. Normally you’d write something like this:
private void button1_Click(object sender, EventArgs e)
{
string input = "Input data";
ThreadPool.QueueUserWorkItem(new WaitCallback(DoStuff), input);
}
private void DoStuff(object o)
{
string input = o as string;
// Long-running computation
}
The WaitCallback delegate can be used on any function that takes a single object input parameter and returns void. An input parameter may be passed as the second argument to QueueUserWorkItem, but it only passed as an object. The DoStuff method must then typecast the input object back to its original type. So, out of the box, the QueueUserWorkItem method is not typesafe, since it only throws around generic objects. This actually causes problems later, as we’ll soon find out.
If you feel so inclined, the above code can be shortened by using an anonymous method and a lambda expression:
private void button2_Click(object sender, EventArgs e)
{
string input = "Input data";
ThreadPool.QueueUserWorkItem(
(o) =>
{
string input2 = o as string;
// Long-running computation
}, input);
}
This inlines the function declaration for the single parameter, o (an object) directly into the arguments to QueueUserWorkItem. This can be useful, for example, if you want to hook a small section of code onto an event but don’t necessarily have a reason or need to give that particular method a name.
What do you do if you want to pass more than one argument to method that handles the long-running computation? Well, one way to do this would be to encapsulate all of the input properties into a class, create an instance of that class, and pass that instance into the QueueUserWorkItem method. Then on the other end, all of the parameters can be extracted as properties of the object that was passed in. The code would go something like this:
public class InputData
{
public InputData(string name, int age)
{
this.Name = name;
this.Age = age;
}
public string Name { get; set; }
public int Age { get; set; }
}
private void button3_Click(object sender, EventArgs e)
{
InputData input = new InputData("Matt", 26);
ThreadPool.QueueUserWorkItem(
(data) =>
{
InputData input2 = data as InputData;
string name = input2.Name;
int age = input2.Age;
// Long-running computation
}, input);
}
Wow, that’s a lot of work, just to pass two pieces of data into the long-running computation. Also, for every different method, you’d need to define a complete contained class to hold all of your arguments. Thankfully there is a better way — using anonymous types, a new feature introduced in C# 3.0.
The new C# compiler lets you declare a class with specific properties in much the same way that we have done above, and generates the code for you without giving the class a specific name. So, we could encapsulate all of our input data into a class by using:
var input = new { Name = "Matt", Age = 26 };
Since we are letting the compiler figure out what the name of the class will be called, we use the “var” keyword, and the compiler takes care of the rest. The implementation of the anonymous type would be almost identical to the InputData class that we created in the previous code snippet, and contain two public properties — one (a string) named “Name”, and another (an int) named Age. The compiler (and Visual Studio) are smart enough to be able to infer the types of the properties according to the type of the value assigned to them. This is extremely powerful.
The real problem comes when we want to pass an instance of this anonymous class into our anonymous method:

Since the input parameter to the anonymous method is just an object, we would usually typecast this into the specific type that we need. Except, however, that this is an anonymous type and we don’t actually know the name of the type to cast it to.
The solution here is to create a generic version of the QueueUserWorkItem method, along with a generic version of the WaitCallback delegate. In this case, the type information can be passed along (including anonymous type information), and Visual Studio can correctly infer the types within the anonymous method. Here’s the code for the typesafe QueueUserWorkItem implementation:
public delegate void WaitCallback(T state);
public static class ThreadPoolHelper
{
public static bool QueueUserWorkItem(T state, WaitCallback callback)
{
return ThreadPool.QueueUserWorkItem(s => callback((T)s), state);
}
}
This defines a generic delegate, WaitCallback, which can be used to refer to any function that takes a single argument of type T, and returns void. Then, the ThreadPoolHelper.QueueUserWorkItem takes two parameters — first, an argument of type T, and secondly, a generic WaitCallback of the same type. Notice that I’ve flipped the order of the arguments (state and callback) to make the code usage more readable. (It seems odd to have to scroll all the way down to the end of the anonymous method to see what the input value is.) Here we’ve used an anonymous method as the non-generic WaitCallback for the non-generic QueueUserWorkItem, and have cast it to the correct type before invoking the generic WaitCallback delegate. We then rewrite our sample code to use the generic version of the QueueUserWorkItem method:
private void button5_Click(object sender, EventArgs e)
{
ThreadPoolHelper.QueueUserWorkItem(
new { Name = "Matt", Age = 26 },
(data) =>
{
string name = data.Name;
int age = data.Age;
// Long-running computation
});
}
Not only is this code elegant and compact, but we also gain type safety and Visual Studio Intellisense support! Take a look:

The anonymous type’s properties were correctly inferred and show up in Intellisense!
So, with a small amount of effort and a firm grasp of generics, anonymous methods, and anonymous types, we can make our code not-only typesafe and easier to read, but also more succinct and less prone to error, especially since we don’t need to define lots of “argument container classes”.
Hope that helps someone.
EDIT: ThreadPool.QueueUserWorkItem is nice for spawning off processes, but you can’t be notified on the UI thread when it’s finished. Using the BackgroundWorker class is a much better approach. Check out my other post about how you can use the BackgroundWorker class with anonymous types as well.
EDIT 6.23.08: Build on the ability to pass anonymous types to an anonymous method and take it a step further! Pass multiple arguments to your anonymous methods with these overloads.
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
May 10th, 2008 at 4:12 pm
Wow. I’m blown away by your “small amount of effort and a firm grasp of generics, anonymous methods, and anonymous types.” Also, your screen shots are awesome, and I’m jealous of your fluid writing style. Are you a grad student? You must not be, or else you wouldn’t have time to write all this… HA!
May 12th, 2008 at 1:59 pm
[...] Use ThreadPool.QueueUserWorkItem With Anonymous Types [...]
June 2nd, 2008 at 8:05 am
Impressive !
I recently have read an article on how to return an anonymous type from method that uses similar approach –> http://tomasp.net/articles/cannot-return-anonymous-type-from-method.aspx
June 3rd, 2008 at 1:20 pm
Excellent article. I had just one issue when implementing, and that’s due to the invalid Generic delegate declaration. it should read like this:
public delegate void WaitCallback(T state);
otherwise you will get compiler errors about the type of T being unknown.
June 3rd, 2008 at 1:26 pm
Thanks Jesse! Glad that it helped.
You’re absolutely right about needed to define a generic delegate for this to work. Actually that definition for the WaitCallback delegate is right above the ThreadPoolHelper code above (but it’s easy to miss).
It’s good to note that the C# compiler does indeed treat WaitCallback(T state) as a completely different entity from WaitCallback(object state). Though it has the same name, its signature is different.
June 14th, 2008 at 3:53 pm
[...] Documentation with SandcastleJeff Garoutte on Generating XML Documentation with Sandcastlematt on Use ThreadPool.QueueUserWorkItem With Anonymous TypesJesse on Use ThreadPool.QueueUserWorkItem With Anonymous TypesIvan on Use [...]
June 21st, 2008 at 11:18 pm
[...] Wrappervalerio.net » Blog Archive » Multithreading and Concurrency in .NET on Use ThreadPool.QueueUserWorkItem With Anonymous Typesmatt on Generating XML Documentation with SandcastleJeff Garoutte on Generating XML Documentation [...]
June 24th, 2008 at 12:09 am
[...] Requiredvalerio.net » Blog Archive » Run Anonymous Methods in Another AppDomain on Use ThreadPool.QueueUserWorkItem With Anonymous Typesvalerio.net » Blog Archive » FizzBuzz the Functional Way on LINQ Extension Method [...]
July 2nd, 2008 at 11:36 am
Nice piece of code there, quite useful once you get into threading, generics and anonymous types (which I love).
I think you got a small typo though on the declaration of the delegate:
public delegate void WaitCallback(T state);
In your code, the generic is missing.
July 2nd, 2008 at 11:37 am
Ha, HTML protection I guess, the code should be:
public delegate void WaitCallback<T>(T state);
July 2nd, 2008 at 11:57 am
Ah, I’d totally missed that typo. Yes, HTML protection in effect. Thanks for the heads up! Fixed
July 2nd, 2008 at 12:01 pm
By the way, as I’ve been using this in my own code, I just found it easier to use the built-in Action<T> delegate instead of defining my own WaitCallback delegate that takes one argument of type T and returns void.
July 3rd, 2008 at 5:10 am
[...] thought this blog post by Matt Valerio was good, and it gave me a few ideas to use in a current test project. He wrote a helper method to [...]
August 9th, 2008 at 6:25 pm
[...] I click on the Run button, I want to execute some code on another thread from the ThreadPool (using ThreadPoolHelper), start the external process, attach a handler to the event that gets fired when a new line is [...]