【发布时间】:2012-10-10 06:43:02
【问题描述】:
在下面的问题中,我发现了一个以类型安全的方式调用 QueueUserWorkItem 的巧妙技巧,您可以传递一个委托而不是 WaitCallBack 和一个对象。然而,它并不像人们期望的那样工作。
这里有一些演示该问题的示例代码和输出。
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 对吗?
【问题讨论】:
-
循环变量捕获,再次。搜索该术语的堆栈溢出。
-
@usr 或者,您可以找到其中一个重复项并投票关闭。这将是更有效的做法。
标签: c# multithreading delegates