Question

I have the following code:

Dictionary<string, WSResponse> responseDictionary = new Dictionary<string, WSResponse>();
List<Task> taskList = new List<Task>();
foreach (string ID in IDs)
{
      string localID = ID;

      Task newTask = Task.Factory.StartNew(() =>
      {
           WSResponse response = Query.GetListFor(localID);                    
           responseDictionary.Add(localID, response);
      });
      taskList.Add(newTask);
}

Task.WaitAll(taskList.ToArray());

On the server where this code is running, our IT team has server monitoring software, and they told us that the software reports that an unsafe static Dictionary is being passed around. My guess is that when I use the Dictionary inside a Task, the dictionary is passed to the Task thread as an unsafe pointer. On the other hand, I might have this completely wrong. I have tried to find some authoritative source talking about this, but failed. Can anyone explain what the runtime does in this case?

btw: We are swaping the Dictionary for a ConcurrentDictionary anyway, so no need for alarm.

Was it helpful?

Solution

How does a dictionary get passed byref to a Task

A Dictionary is a reference type so it doesn't matter too much if it is passed by-value or by-ref. But as it happens closure is mostly like by-ref.

In your code:

Dictionary<string, WSResponse> responseDictionary = ...;

  Task newTask = Task.Factory.StartNew(() =>
  {
       WSResponse response = Query.GetListFor(localID);                    
       responseDictionary.Add(localID, response);
  });

The dictionary is declared outside the scope of the Task lambda but the lambda does use it by name. This is allowed and called 'closing over' the variable.

And that means that multiple threads can access your Dictionary and it should be replaced by a ConcurrentDictionary. Most likely that will solve the diagnostic message.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top