This is a classic problem for / capture, because you capture j , and there is only one j . All your threads are processed using the same j variable; the value they see is undefined, but the last few threads most likely see the exit value of the loop, that is, too much.
Instead
for (int loopIndex = 0; loopIndex < temp; loopIndex++) { int j = loopIndex;
it sounds silly, but now you have iteration j on each loop, because the capture area depends on the variable declaration area. Here j is defined inside the loop. In a for loop, a variable is technically defined outside the loop.
Another way to do this is to use a parameter in the thread pool:
for(int loopIndex = 0; loopIndex < temp; loopIndex++) { ThreadPool.QueueUserWorkItem(delegate(object ctx) { int j = (int) ctx;
Here is an extended version of how the "captured variables" and anonymous methods work, a more simplified version; Firstly, the compiler does this for you:
class CaptureContext {
and your method becomes (since j technically defined outside the loop):
var ctx = new CaptureContext(); for (ctx.j = 0; ctx.j < temp; ctx.j++) { ThreadPool.QueueUserWorkItem(ctx.SomeMethod); }
currently; you see that there is only one βcaptureβ object, and we use it at random points at times when ctx.j not necessarily what we thought it was? The fix overwrites this as:
for (int loopIndex = 0; loopIndex < temp; loopIndex++) { var ctx = new CaptureContext(); ctx.j = loopIndex; ThreadPool.QueueUserWorkItem(ctx.SomeMethod); }
here you see that there is a capture object to iterate because j declared internally in a loop? βWhat is the new capture contextβ depends on the scope of the captured variables.