(有时)字典中没有给定的键

时间:2013-05-20 07:37:51

标签: c# multithreading dictionary

我使用下面的代码来启动带有list参数的线程,但有时会引发异常:

  

字典中没有给定的密钥

从这一行:

Thread MoveThread = new Thread(() => MoveTask(ControllerDictionary[i]));

如何修复该错误?

完整代码:

var ControllerDictionary = ConfigFile.ControllerList.Select((c, i) => new { Controller = c, Index = i })
    .GroupBy(x => x.Index % AppSettings.SimultaneousProcessNumber)
    .Select((g, i) => new { GroupIndex = i, Group = g })
    .ToDictionary(x => x.GroupIndex, x => x.Group.Select(xx => xx.Controller).ToList());

for (int i = 0; i < ControllerDictionary.Count; i++)
{
     Thread MoveThread = new Thread(() => MoveTask(ControllerDictionary[i]));
     MoveThread.Start();

     foreach (var Controller in ControllerDictionary[i])
         Logger.Write(string.Format("{0} is in move thread {1}.", Controller.Ip, (i + 1)),EventLogEntryType.Information, AppSettings.LogInfoMessages);
}

2 个答案:

答案 0 :(得分:8)

您正在捕获变量 i,而不是其值。因此,目前您可以使用相同的索引调用MoveTask多个线程...有时i的值可能等于ControllerDictionary.Count

如果你将i副本带入循环中的变量,那就解决了问题,因为你将在循环的每次迭代中得到一个单独的变量:

for (int i = 0; i < ControllerDictionary.Count; i++)
{
    int index = i;
    Thread MoveThread = new Thread(() => MoveTask(ControllerDictionary[index]));
    ... 
}

甚至更好,完全从线程中提取ControllerDictionary提取:

for (int i = 0; i < ControllerDictionary.Count; i++)
{
    var value = ControllerDictionary[i];
    Thread MoveThread = new Thread(() => MoveTask(value));
    ... 
}

此外,为什么你要使用字典并不是很清楚。鉴于您知道密钥将全部在[0, count)范围内,为什么不使用数组?您将查询更改为:

var controllerLists = ConfigFile.ControllerList
    .Select((c, i) => new { Controller = c, Index = i })
    .GroupBy(x => x.Index % AppSettings.SimultaneousProcessNumber)
    .Select(g => g.Select(xx => xx.Controller).ToList())
    .ToArray();

答案 1 :(得分:2)

问题在于:

Thread MoveThread = new Thread(() => MoveTask(ControllerDictionary[i]));

该匿名函数将在另一个线程上执行,并且无法保证局部变量有效。