using Core.WcfProtocol; using System.Collections.Concurrent; namespace SHH.MjpegPlayer { /// 图片通道集合 public class ImageChannels { #region Channels /// /// 通道信息 (线程安全版本) /// // [修复] 使用 ConcurrentDictionary 替代 Dictionary,防止多线程读写(如推流和接收图片同时进行)时崩溃 public ConcurrentDictionary Channels { get; set; } = new ConcurrentDictionary(); #endregion #region Do /// /// 处置图片 /// /// /// public ImageChannel? Do(UploadImageRequest req, string key) { // [修复] 使用 GetOrAdd 原子操作,无需 lock,彻底解决并发冲突 // 如果 key 不存在,则创建新通道;如果存在,则返回现有通道 var chn = Channels.GetOrAdd(key, k => new ImageChannel { DeviceId = req.Id, Name = req.Name, Type = req.Type, }); // 更新指定信息 (直接属性赋值是原子性的,无需锁) chn.IpAddress = req.IpAddress; chn.ProcId = req.ProcId; chn.ImageWidth = req.ImageWidth; chn.ImageHeight = req.ImageHeight; chn.UpdateTime = req.Time; return chn; } #endregion #region Get /// /// 获取通道信息 /// /// /// /// public ImageChannel? Get(string deviceId, string aiTypeCode) { string key = $"{deviceId}#{aiTypeCode}"; // [修复] ConcurrentDictionary 读取原本就是线程安全的 if (Channels.TryGetValue(key, out var val)) { return val; } return null; } #endregion } }