问题
I'm having a problem with
foreach(var category in categories)
{
foreach(var word in words)
{
var waitCallback = new WaitCallback(state =>
{
DoSomething(word, category);
});
ThreadPool.QueueUserWorkItem(waitCallback);
}
}
When the DoSomething
gets executed, it receives the latest value for each captured variable instead of the value I desired. I can imagine a solution for this, but it imagine you guys can come up with better solutions
回答1:
The canonical way to solve this is to copy the values into temporary variables which are declared inside the loop.
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);
}
}
回答2:
Refactor it to:
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);
}
This is simple and easy to understand. It states the developer's intent without cluttering the code with extra variables (as in the default way to solve this problem).
回答3:
For reference, I imagine the following would solve my problem:
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);
}
}
回答4:
I would write the whole thing like this, which dodges the problem and leaves absolutely no question about what is going on:
var callbacks = words.SelectMany(w => categories.Select(c =>
new WaitCallback(state => {
DoSomething(w, c);
})
));
foreach (var callback in callbacks)
ThreadPool.QueueUserWorkItem(callback);
来源:https://stackoverflow.com/questions/5717186/how-to-avoid-captured-variables