在下面的问题中,我发现了一种调用QueueUserWorkItem的巧妙方法,以类型安全的方式传递委托而不是WaitCallBack和对象。然而,它并不像人们期望的那样工作。
这里有一些示例代码和输出,演示了这个问题。
链接:QueueUserWorkItem()和BeginInvoke()有什么区别,用于执行不需要返回类型的异步操作
请注意,使用闭包调用QueueUserWorkitem时,每次调用i都为10,但是使用WaitCallBack时可以得到正确的值0-9。
所以我的问题是:
1.为什么使用闭包/委托的方式时没有传递正确的i值?
2.i怎么可能变成10?在循环中,它只有0-9的值,对吗?
这里有一些示例代码和输出,演示了这个问题。
链接: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。
所以我的问题是:
1.为什么使用闭包/委托的方式时没有传递正确的i值?
2.i怎么可能变成10?在循环中,它只有0-9的值,对吗?