我的foreach循环未遍历所有元素?C#定时器代码故障排查
问题描述
该代码旨在每100ms序列化所有对象并发送至其他程序,每200ms将序列化对象写入文件用于后续回放(另有代码负责读取这些文件)。但实际运行后,仅有“hammers”被输出,且仅打印0。已通过断点确认集合已正确填充,请问问题出在哪里?
原代码
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; namespace Helper { public static class Program { public static bool active = false; public static WorldData wdataTest = new WorldData(); // Simple test objects public static Dictionary<string, WorldData> dic = new Dictionary<string, WorldData>(); public static void Main() { active = true; Start(); } public static void Start() { dic.Add("test", wdataTest); System.Timers.Timer timer = new System.Timers.Timer(); string serialized; bool loaded = false; int i = -10; int normalizedRate = 2; timer.Interval = 100; timer.AutoReset = true; timer.Elapsed += new System.Timers.ElapsedEventHandler((_, __) => { try { Stopwatch st = new Stopwatch(); st.Start(); if (active) { if (loaded) { i++; } foreach (WorldData wData in dic.Values) { loaded = true; foreach (EntityList collection in wData.collectionOfCollections) { serialized = JsonConvert.SerializeObject(collection.Entities); // Does some other things if (i == normalizedRate) { WriteSerialized(collection, serialized); i = 0; } } } } st.Stop(); Console.WriteLine(st.ElapsedMilliseconds.ToString()); } catch (Exception e) { Console.WriteLine(e.Message); } }); timer.Enabled = true; Console.ReadKey(); } public static void WriteSerialized(EntityList collection, string serializedObj) { Console.WriteLine(collection.Name); // Write to file serializedObj } public class WorldData { public List<EntityList> collectionOfCollections; public WorldData() { collectionOfCollections = new List<EntityList>(); collectionOfCollections.Add(new EntityList("hammers")); collectionOfCollections.Add(new EntityList("screwdrivers")); collectionOfCollections.Add(new EntityList("nails")); collectionOfCollections.Add(new EntityList("pcs")); } } public class EntityList { public List<object> Entities; public string Name { get; set; } public EntityList(string name) { Name = name; Entities = new List<object>(); Entities.Add(new object()); } } } }
问题根源
1. 计数器逻辑错误导致仅单个集合触发写入
当i == normalizedRate(即i=2)时,处理第一个EntityList(hammers)后会立刻将i重置为0,后续的screwdrivers、nails、pcs循环时,i已经不满足等于2的条件,因此不会触发写入。
2. loaded变量逻辑混乱
loaded初始为false,第一次定时器触发时i不会递增,但进入WorldData循环后立即将loaded设为true,导致本次触发的后半段逻辑中loaded状态异常,后续计数逻辑混乱。
3. 多线程变量访问无同步
i、loaded、active这些变量在主线程定义,却在定时器的Elapsed线程中修改读取,没有线程同步机制,可能导致变量状态不可预期。
修复方案
调整逻辑,确保计数达标时所有集合都执行写入,同时保证线程安全:
修改后代码
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; namespace Helper { public static class Program { public static bool active = false; public static WorldData wdataTest = new WorldData(); public static Dictionary<string, WorldData> dic = new Dictionary<string, WorldData>(); private static readonly object _lockObj = new object(); // 线程同步锁 public static void Main() { active = true; Start(); } public static void Start() { dic.Add("test", wdataTest); System.Timers.Timer timer = new System.Timers.Timer(); string serialized; int i = 0; int normalizedRate = 2; timer.Interval = 100; timer.AutoReset = true; timer.Elapsed += new System.Timers.ElapsedEventHandler((_, __) => { try { Stopwatch st = new Stopwatch(); st.Start(); lock (_lockObj) { if (active) { i++; bool needWrite = i == normalizedRate; foreach (WorldData wData in dic.Values) { foreach (EntityList collection in wData.collectionOfCollections) { serialized = JsonConvert.SerializeObject(collection.Entities); // 执行序列化后的发送逻辑 if (needWrite) { WriteSerialized(collection, serialized); } } } if (needWrite) { i = 0; } } } st.Stop(); Console.WriteLine(st.ElapsedMilliseconds.ToString()); } catch (Exception e) { Console.WriteLine(e.Message); } }); timer.Enabled = true; Console.ReadKey(); } public static void WriteSerialized(EntityList collection, string serializedObj) { Console.WriteLine(collection.Name); // Write to file serializedObj } public class WorldData { public List<EntityList> collectionOfCollections; public WorldData() { collectionOfCollections = new List<EntityList>(); collectionOfCollections.Add(new EntityList("hammers")); collectionOfCollections.Add(new EntityList("screwdrivers")); collectionOfCollections.Add(new EntityList("nails")); collectionOfCollections.Add(new EntityList("pcs")); } } public class EntityList { public List<object> Entities; public string Name { get; set; } public EntityList(string name) { Name = name; Entities = new List<object>(); Entities.Add(new object()); } } } }
关键修改点
- 移除冗余的
loaded变量,每次定时器触发直接递增i - 提前判断本次是否需要写入(
needWrite),确保所有集合都能执行写入操作 - 所有集合处理完成后再重置
i,避免中断后续集合的写入逻辑 - 添加
lock语句,保证多线程下变量访问的安全性
内容的提问来源于stack exchange,提问作者MrBott_a
相关产品推荐
相关产品推荐

