在下面的问题中,我发现了一个以类型安全的方式调用 QueueUserWorkItem 的巧妙技巧,您可以在其中传递一个委托而不是 WaitCallBack 和一个对象。然而,它并不像人们期望的那样工作。
QueueUserWorkItem() 和 BeginInvoke() 之间有什么区别,用于执行不需要返回类型的异步活动
这是一些演示该问题的示例代码和输出。
for (int i = 0; i < 10; ++i)
{
// doesn't work - somehow DoWork is invoked with i=10 each time!!!
ThreadPool.QueueUserWorkItem(delegate { DoWork("closure", i); });
// not type safe, but it works
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), Tuple.Create(" WCB", i));
}
void DoWork(string s, int i)
{
Console.WriteLine("{0} - i:{1}", s, i);
}
void DoWork(object state)
{
var t = (Tuple<string, int>)state;
DoWork(t.Item1, t.Item2);
}
这是输出:
closure - i:10
WCB - i:0
closure - i:10
WCB - i:2
WCB - i:3
closure - i:10
WCB - i:4
closure - i:10
WCB - i:5
closure - i:10
WCB - i:6
closure - i:10
WCB - i:7
closure - i:10
WCB - i:8
closure - i:10
WCB - i:9
WCB - i:1
closure - i:10
请注意,当使用闭包调用 QueueUserWorkitem 时,i=10 永远调用,但是当使用 WaitCallBack 时,您会得到正确的值,0-9。
所以我的问题是:
- 为什么在使用闭包/委托方式时没有传递正确的 i 值?
- 我到底是怎么到10岁的?在循环中,它只有值 0-9 对吗?