错误分析报错信息为:System.InvalidOperationException: 集合已修改;可能无法执行枚举操作。
这表明在遍历 m_BIBInfoMap.Values 集合时,集合被修改(例如添加、删除或替换元素),导致枚举器失效。
这是 .NET 中常见的异常,通常发生在使用 foreach 遍历集合时,集合的内容被修改。
具体错误发生在以下代码块中:csharp
foreach (BIB bib in m_BIBInfoMap.Values)
{
// ...
m_BIBInfoMap[bib.Id] = CurrentSetBIBBoard; // 修改 m_BIBInfoMap
// ...
}
在 foreach 遍历 m_BIBInfoMap.Values 时,代码通过 m_BIBInfoMap[bib.Id] = CurrentSetBIBBoard 修改了 m_BIBInfoMap 集合。这会导致正在使用的枚举器失效,抛出 InvalidOperationException。
优化方案为了解决这个问题,我们需要确保在遍历集合时不直接修改它。
以下是几种解决方案,以及优化的代码实现:
方案一:使用 ToList() 创建副本进行遍历通过将 m_BIBInfoMap.Values 转换为一个新的 List,我们可以安全地遍历副本,而不会影响原始集合。
方案二:使用临时集合存储修改内容将需要修改的键值对存储到一个临时集合中,待遍历完成后统一更新 m_BIBInfoMap。
方案三:使用普通 for 循环如果需要直接操作 m_BIBInfoMap,可以通过索引或键值访问,避免使用枚举器。
以下基于 方案一 提供优化后的代码,因为它简单且易于理解,同时保持代码逻辑不变。
优化后的代码csharp
public static void UpdateBIBBoardSectionId(string sectionId, string BIBBoard)
{
try
{
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings", "BIBBoard.ini");
StringBuilder sb = new StringBuilder();
var testSection = GetSection(sectionId);
// 使用 ToList() 创建副本,避免在遍历时修改集合
foreach (BIB bib in m_BIBInfoMap.Values.ToList())
{
string channelIDbib = bib.ChannelID;
foreach (TestChannel testChannel1 in testSection.TestChannelMap.Values)
{
var channelID = testChannel1.Id;
if (bib.HardwareStatus == HardwareStatus.Enabled && channelID == channelIDbib)
{
var currentSetBIBBoard = HardwareMgr.CopyBIB(HardwareMgr.BIBMap[BIBBoard]);
// 更新 BIB 对象的属性
currentSetBIBBoard.Id = bib.Id;
currentSetBIBBoard.BIBName = bib.BIBName;
currentSetBIBBoard.Life = bib.Life;
currentSetBIBBoard.HardwareStatus = bib.HardwareStatus;
currentSetBIBBoard.BIBCoords = bib.BIBCoords;
currentSetBIBBoard.ChannelID = bib.ChannelID;
// 更新 m_BIBInfoMap
m_BIBInfoMap[bib.Id] = currentSetBIBBoard;
// 更新 TestChannel 的 Bib 属性
TestChannel testChannel = GetChannel(channelID);
testChannel.Bib = currentSetBIBBoard;
}
}
}
// 序列化并写入文件
foreach (string bibID in m_BIBInfoMap.Keys)
{
sb.AppendLine(JsonConvert.SerializeObject(m_BIBInfoMap[bibID]));
}
File.WriteAllText(filePath, sb.ToString());
}
catch (Exception ex)
{
// 日志记录,方便调试
Console.WriteLine($"更新 BIBBoardSectionId 失败: {ex.Message}");
throw; // 抛出异常以便上层处理
}
}
优化点详解
- 修复集合修改问题:
- 在 foreach (BIB bib in m_BIBInfoMap.Values) 中添加 .ToList(),将 m_BIBInfoMap.Values 复制到一个新列表中。这样,遍历的是副本,修改原始 m_BIBInfoMap 不会影响遍历过程,解决了 InvalidOperationException。
- 改进路径处理:
- 将文件路径拼接从 AppDomain.CurrentDomain.BaseDirectory + "Settings\\BIBBoard.ini" 改为使用 Path.Combine,提高代码的可读性和跨平台兼容性。
- 变量命名优化:
- 将 fledpath 更名为 filePath,修正拼写错误并提高可读性。
- 将 sb_1 更名为 sb,简化命名。
- 将 CurrentSetBIBBoard 更名为 currentSetBIBBoard,遵循 C# 命名规范(变量名首字母小写)。
- 异常处理改进:
- 原代码的 catch 块为空,捕获异常但不做任何处理,这可能导致问题被忽略。优化后添加了日志输出(Console.WriteLine),并重新抛出异常(throw),以便上层代码能够感知并处理异常。
- 建议在实际生产环境中使用更健壮的日志框架(如 Serilog 或 NLog)代替 Console.WriteLine。
- 代码结构优化:
- 保持逻辑清晰,确保每个步骤(遍历、更新、序列化、写入文件)分块明确。
- 使用更具描述性的变量名(如 currentSetBIBBoard),提高代码可维护性。
其他建议


4656

被折叠的 条评论
为什么被折叠?



