(有时)给定的键在字典中不存在

本文关键字:字典 不存在 有时 | 更新日期: 2023-09-27 18:14:26

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

给定的键在字典中不存在

从这行开始:

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);
}

(有时)给定的键在字典中不存在

您捕获的是变量 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();

问题就在这里:

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

该匿名函数将在另一个线程上执行,并且不能保证局部变量是有效的