I was about to ask a question, but guessed it, and decided to post the question and answer - or at least my observations.
When using an anonymous delegate like WaitCallback, where ThreadPool.QueueUserWorkItem is called in a foreach loop, it seems that the same foreach value is passed to each thread.
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 ); } } }
For a collection of 16 Thing instances in Things, I noticed that each "Thing" passed to WorkWithOneThing corresponds to the last item in the list of "things."
I suspect this is because the delegate accesses the external variable 't'. Note that I also experimented with passing Thing as a parameter to an anonymous delegate, but the behavior remained incorrect.
When I redefined the code to use the WaitCallback method and passed Thing 't' to the method, alt ... the ith instance of Things was correctly passed to WorkWithOneThing.
A lesson in parallelism I think. I also assume that the Parallel.For family is addressed to this, but this library was not an option for us at the moment.
Hope this saves you a little time.
Howard Hoffman
closures c #
Howard hoffman
source share