2

Having a tight loop that queues work to different threads by calling QueueUserWorkItem.

I was wondering if each loop execution could potentially be changing what was passed as the argument to the previous pool thread.

List<object> list = new List<object>();

for (int i = 0; i < list.Count; i++)
{
    object param = list[i];
    ThreadPool.QueueUserWorkItem(x => { MethodWithParameter(x); }, param);
}
Nico
  • 12,493
  • 5
  • 42
  • 62
Stefano
  • 529
  • 1
  • 4
  • 4

1 Answers1

2

I was wondering if each loop execution could potentially be changing what was passed as the argument to the previous pool thread

No, the part of your code that is queuing up the task into the pool is synchronous

// here you are assigning the value that 
// will be used as the state for the task when it is run
object param = list[i];
ThreadPool.QueueUserWorkItem(x => { MethodWithParameter(x); }, param);

So whatever the value of param is at the point of the invocation of the method QueueUserWorkItem will be passed as x when the task starts

You could get into trouble doing something like this:

object param = null;
for (int i = 0; i < list.Count; i++)
{
    //even though you are assigning a value to param here
    //there is no telling when the task will actually execute
    param = list[i];
    ThreadPool.QueueUserWorkItem(x => { MethodWithParameter(param); }, null);
}

Because there is no telling what the value of param will be when the task is actually executed.

konkked
  • 3,161
  • 14
  • 19
  • Side note: obviously if list filled with the same item all bets are off... But indeed this code solves problem with closures and `foreach` in pre-C#5 (http://stackoverflow.com/questions/512166/the-foreach-identifier-and-closures) – Alexei Levenkov Aug 09 '16 at 21:53
  • My question rises from probably my misinterpreting the following comment http://stackoverflow.com/questions/30225476/task-run-with-parameters#comment48555456_30225551. From Zer0's comment starting a thread using `QueueUserWorkItem` and using `Task.Run` seems to incur the same potential issue with passed arguments but this is not true. Am I misinterpreting something? – Stefano Aug 10 '16 at 08:45
  • @Stefano : Zer0's comment is wrong there, the reference that is passed at the time of invocation is what will be passed in as the state into the worker item, you can see a demo proving that comment wrong here : https://dotnetfiddle.net/56arkp – konkked Aug 10 '16 at 14:52