我遇到了
的问题foreach(var category in categories)
{
foreach(var word in words)
{
var waitCallback = new WaitCallback(state =>
{
DoSomething(word, category);
});
ThreadPool.QueueUserWorkItem(waitCallback);
}
}
执行DoSomething
时,它会接收每个捕获变量的最新值,而不是我想要的值。我可以想象一个解决方案,但它想象你们可以提出更好的解决方案
答案 0 :(得分:13)
解决此问题的规范方法是将值复制到临时变量中,这些变量在循环中声明为
。foreach(var category in categories)
{
var catCopy = category;
foreach(var word in words)
{
var wordCopy = word;
var waitCallback = new WaitCallback(state =>
{
DoSomething(wordCopy, catCopy);
});
ThreadPool.QueueUserWorkItem(waitCallback);
}
}
答案 1 :(得分:4)
Refactor来:
foreach(var category in categories) {
foreach(var word in words) {
DoSomethingAsync(word, category);
}
}
...
private void DoSomethingAsync(string word, string category) {
var waitCallback = new WaitCallback(state => DoSomething(word, category));
ThreadPool.QueueUserWorkItem(waitCallback);
}
这很简单易懂。它说明了开发人员的 intent ,而没有使用额外的变量使代码混乱(如解决此问题的默认方式)。
答案 2 :(得分:1)
作为参考,我想以下可以解决我的问题:
foreach(var category in categories)
{
foreach(var word in words)
{
var waitCallback = new WaitCallback(state =>
{
var kv = (KeyValuePair<string, string>)state;
DoSomething(kv.Key, kv.Value);
});
var state2 = new KeyValuePair<string, string>(word, category);
ThreadPool.QueueUserWorkItem(waitCallback, state2);
}
}
答案 3 :(得分:1)
我会写出这样的全部内容,它会避开问题并且完全没有问题:
var callbacks = words.SelectMany(w => categories.Select(c =>
new WaitCallback(state => {
DoSomething(w, c);
})
));
foreach (var callback in callbacks)
ThreadPool.QueueUserWorkItem(callback);