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

san*_*p22 1 c# multithreading dictionary

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

给定的密​​钥不在字典中

从这一行:

Thread MoveThread = new Thread(() => MoveTask(ControllerDictionary[i]));
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个错误?

完整代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 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]));
    ... 
}
Run Code Online (Sandbox Code Playgroud)

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

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

另外,为什么你要使用字典还不是很清楚.鉴于您知道键将全部在范围内,[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();
Run Code Online (Sandbox Code Playgroud)