ThreadPool.QueueUserWorkItem With Multiple Arguments

Awhile back I wrote a post about how to create a generic (and type-safe) version of the ThreadPool.QueueUserWorkItem method.  It really opened up a lot of possibilities since the C# compiler was able to use type inference for the object that was passed to the delegate.

As it turns out, being able to pass anonymous types to the delegate really opens up a lot of possibilities.  I think that part of the benefit of passing an anonymous type to the WaitCallback delegate was to pass multiple arguments.  So I was thinking….why not just abstract that away too?  Here’s my expanded version of ThreadPoolHelper that lets you pass multiple arguments to your method without having to create the anonymous type yourself.

        public static bool QueueUserWorkItem(Action callback)

        {

            return ThreadPool.QueueUserWorkItem((o) => callback());

        }

 

        public static bool QueueUserWorkItem<T>(T arg, Action<T> callback)

        {

            return ThreadPool.QueueUserWorkItem(s => callback((T)s), arg);

        }

 

        public static bool QueueUserWorkItem<T1, T2>(T1 arg1, T2 arg2, Action<T1, T2> callback)

        {

            return ThreadPoolHelper.QueueUserWorkItem(

                new { Arg1 = arg1, Arg2 = arg2 },

                (args) =>

                {

                    callback(args.Arg1, args.Arg2);

                });

        }

 

        public static bool QueueUserWorkItem<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3, Action<T1, T2, T3> callback)

        {

            return ThreadPoolHelper.QueueUserWorkItem(

                new { Arg1 = arg1, Arg2 = arg2, Arg3 = arg3 },

                (args) =>

                {

                    callback(args.Arg1, args.Arg2, args.Arg3);

                });

        }

 

        public static bool QueueUserWorkItem<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, Action<T1, T2, T3, T4> callback)

        {

            return ThreadPoolHelper.QueueUserWorkItem(

                new { Arg1 = arg1, Arg2 = arg2, Arg3 = arg3, Arg4 = arg4 },

                (args) =>

                {

                    callback(args.Arg1, args.Arg2, args.Arg3, args.Arg4);

                });

        }

I’m just reusing the functionality of the first method (with one type parameter) for the rest (2, 3, and 4 type parameters).  The type in these cases is an anonymous type with 2, 3, and 4 properties :)

So, that takes care of you from 0 to 4 arguments.  That’s just enough to handle the 4 overloads for the generic Action delegate, but you could of course define your own Action delegate that takes 5 or more type parameters.

I also got rid of the generic WaitCallback<T> delegate, since it had the exact same signature as Func<T>.  Might as well reuse Func<T> if it’s already there.

Using these guys is pretty straightforward (which is kinda the point):

            ThreadPoolHelper.QueueUserWorkItem(

                1001,

                "A string?",

                4.3d,

                EventArgs.Empty,

                (i, s, d, e) =>

                {

                    // Do something sweet here

                });

All four types can be inferred from the compiler (and Visual Studio’s Intellisense). 

Hope someone finds that useful!  I know it’s saved me a lot of typing.


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.

AddThis Social Bookmark Button

9 Responses to “ThreadPool.QueueUserWorkItem With Multiple Arguments”

  1. […] ThreadPool.QueueUserWorkItem With Multiple Arguments […]

  2. Damn, I just came up with this too and was posting it as a reply to the initial post, when I saw you figured it out yourself. :-)

    Good work! I really loved this solution and can put it to good use in my work.

    Thanks!

  3. […] ThreadPool.QueueUserWorkItem With Multiple Arguments […]

  4. Hi It was a nice example,but to pass multiple arguments the callback in QueueUserWorkItem I think we can go like below

    Hashtable temp1 = new Hashtable();
    Hashtable temp2 = new Hashtable();

    ThreadPool.QueueUserWorkItem(delegate{display(temp1,temp2);});

    public void display(Hashtable t1,Hashtable t2){
    //do something with t1,t2
    }

    It works for me and i am not sure if we have any pitfalls in the above approach.

  5. […] ThreadPool.QueueUserWorkItem With Multiple Arguments […]

  6. Greate job, but Action can take four parameters only.
    How can you define QueueUserWorkItem with 5 parameters.
    Thank you.

  7. Nice work!

  8. MattMuenzner Says:

    Hey its awesome thanks alot!

    Here is the VB Translation i made:

    Public Shared Function QueueUserWorkItem(Of T)(ByVal state As T, ByVal callback As Action(Of T)) As Boolean

    Return ThreadPool.QueueUserWorkItem(Sub(o) callback(CType(o, T)), state)

    End Function

    Public Shared Function QueueUserWorkItem(Of T, U)(ByVal state As T, ByVal state2 As U, ByVal callback As Action(Of T, U)) As Boolean

    Return ThreadPoolHelper.QueueUserWorkItem(New With {Key .Args1 = state, .Args2 = state2}, Sub(o) callback(o.Args1, o.Args2))

    End Function

  9. I couldn’t get your code to compile…

    return ThreadPool.QueueUserWorkItem((o) => callback());

    Error: callback is a ‘variable’ and is being used like a ‘method.’

Leave a Reply