using System.Collections.Concurrent; using System.Net.NetworkInformation; namespace WCS.Core; public class PLC : EntityEx { public PLC(PLCInfo ent, World world) : base(ent) { if (Configs.PLCAccessorCreater != null) Accessor = Configs.PLCAccessorCreater.Create(ent); else throw new Exception("Configs.PLCAccessorCreater未赋值"); IPDetection.AddIP(Entity.IP); } public bool Ping { get => IPDetection.GetIpStatus(Entity.IP); } public IPLCAccessor Accessor { get; private set; } } public class IPDetection { /// /// 需要检测的IP组,使用线程安全的字典 /// private static ConcurrentDictionary _ipDetection = new ConcurrentDictionary(); /// /// 是否启动检测器 /// private static bool isStart = false; /// /// 取消标记,用于停止检测任务 /// private static CancellationTokenSource cancellationTokenSource; /// /// 添加IP进行检测 /// /// public static void AddIP(string ip) { if (!_ipDetection.ContainsKey(ip)) { _ipDetection[ip] = false; // 默认为不在线 } if (!isStart) { isStart = true; Start(); } } /// /// 获取指定IP的状态 /// /// /// public static bool GetIpStatus(string ip) { return _ipDetection.ContainsKey(ip) && _ipDetection[ip]; } /// /// 启动IP检测任务 /// private static void Start() { cancellationTokenSource = new CancellationTokenSource(); Task.Run(async () => { while (!cancellationTokenSource.Token.IsCancellationRequested) { await CheckIpsAsync(); await Task.Delay(1000); // 等待 1 秒 } }, cancellationTokenSource.Token); } /// /// 停止IP检测任务 /// public static void Stop() { cancellationTokenSource?.Cancel(); isStart = false; } /// /// 检测所有IP的状态 /// /// private static async Task CheckIpsAsync() { var tasks = new List(); foreach (var ip in _ipDetection.Keys.ToList()) // 使用 ToList 防止遍历时修改字典 { tasks.Add(Task.Run(async () => { bool isOnline = await PingAsync(ip); _ipDetection[ip] = isOnline; })); } await Task.WhenAll(tasks); } /// /// pingIp /// /// /// private static async Task PingAsync(string ip) { try { if (ip == "1") return false; Ping ping = new Ping(); PingReply reply = await ping.SendPingAsync(ip, 300); // 设置超时时间为300毫秒 return reply.Status == IPStatus.Success; } catch { // 如果出现异常,认为该IP不可用 return false; } } } public interface IPLCAccessorCreater { IPLCAccessor Create(PLCInfo data); } public interface IPLCAccessor { void WriteBytes(ushort db, ushort address, byte[] data); byte[] ReadBytes(ushort db, ushort address, ushort length); }