如何使用QueueUserWorkItem的两种变体

时间:2015-10-29 15:11:01

标签: c# multithreading

尝试了解ThreadPool方法QueueUserWorkItem的两种变体。

string bigS = "Big Stupid";
ThreadPool.QueueUserWorkItem( s =>
{
    Console.WriteLine("Working on a thread from threadpool B");
    Console.WriteLine("s = {0}", s.ToString());
}, bigS);

ThreadPool.QueueUserWorkItem(MethodA, bigS);

MethodA的定义如下。

private static void MethodA(object o)
{
    Console.WriteLine("o = {0}", o.ToString());
}

两种方式都很好。但是QueueUserWorkItem还有另一种变体,它接受一个采用单个参数并返回void的方法的委托。所以methodA应该没问题。但是由于我没有在o中传递对象MethodA,因此跟随代码抛出异常。我不想在o中检查MethodA的空值。如何将第二种情况中的bigS传递给MethodA

ThreadPool.QueueUserWorkItem(MethodA);

替代方式可能是这样的。但我想通过并访问o。我能做到吗?

ThreadPool.QueueUserWorkItem( o =>
{
Console.WriteLine("Working on a thread from threadpool");
});

2 个答案:

答案 0 :(得分:1)

It's not very clear from the MSDN documentation, but

ThreadPool.QueueUserWorkItem(callback);

is equivalent to

ThreadPool.QueueUserWorkItem(callback, null);

If optional parameters existed at the time this API has been made, most probably there would have been just one method like

public static bool QueueUserWorkItem(WaitCallback callBack, object state = null)

But for one thing the documentation (the Remarks section) is clear - if you want your callback to receive something, you need to pass it, i.e. use the overload with state argument.

答案 1 :(得分:1)

The o in

ThreadPool.QueueUserWorkItem( o =>
{
    Console.WriteLine("Working on a thread from threadpool");
});

will always be null. It is just there because QueueUserWorkItem wants a WaitCallback and that is defined as an Action<object>. I think microsoft devs just don´t wanted to define a second WaitCallback delegate. And ThreadPool was implemented before Action and Func existed.

You could capture the bigS with your lambda

string bigS = "Big Stupid";
ThreadPool.QueueUserWorkItem( _ =>
{
    Console.WriteLine("Working on a thread from threadpool B");
    Console.WriteLine("s = {0}", bigS);
});

or like this if you have to use MethodA

string bigS = "Big Stupid";
ThreadPool.QueueUserWorkItem( _ =>
{
    MethodA(bigS);
});