(有时)字典中没有给定的键
我使用下面的代码启动带有list参数的线程,但有时它会引发exception:
给定的密钥不在字典中
从这一行:
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 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)
范围内[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]));
该匿名函数将在不同的线程上执行,并且无法保证局部变量有效。