我打算发布一个问题,但提前弄清楚并决定发布问题和答案 - 或者至少是我的观察结果。
当使用匿名委托作为 WaitCallback 时,在 foreach 循环中调用 ThreadPool.QueueUserWorkItem 时,似乎将相同的一个 foreach-value 传递到每个线程。
List< Thing > things = MyDb.GetTheThings();
foreach( Thing t in Things)
{
localLogger.DebugFormat( "About to queue thing [{0}].", t.Id );
ThreadPool.QueueUserWorkItem(
delegate()
{
try
{
WorkWithOneThing( t );
}
finally
{
Cleanup();
localLogger.DebugFormat("Thing [{0}] has been queued and run by the delegate.", t.Id );
}
});
}
对于 Things 中 16 个 Thing 实例的集合,我观察到传递给 WorkWithOneThing 的每个“Thing”都对应于“things”列表中的最后一项。
我怀疑这是因为委托正在访问“t”外部变量。请注意,我还尝试将 Thing 作为参数传递给匿名委托,但行为仍然不正确。
当我重构代码以使用命名的 WaitCallback 方法并将 Thing 't' 传递给该方法时,瞧……Thing 的第 i 个实例被正确传递到 WorkWithOneThing。
我猜是并行性的一课。我还想象 Parallel.For 家族解决了这个问题,但此时该库不是我们的选择。
希望这可以节省其他人一些时间。
霍华德霍夫曼