瀏覽代碼

优化 PLC 类并新增 IP 检测功能

添加对 System.Collections.Concurrent 的引用以支持线程安全的字典操作。简化 PLC 类构造函数,新增 IPDetection 类以管理 IP 地址的检测,包括添加 IP、获取状态、启动和停止检测任务。实现异步检测方法 CheckIpsAsync 和 PingAsync,提升代码结构和功能的清晰度,支持多线程环境下的 IP 检测。
林豪 左 3 月之前
父節點
當前提交
cfbbc65f81
共有 1 個文件被更改,包括 113 次插入18 次删除
  1. 113 18
      WCS.Core/PLC.cs

+ 113 - 18
WCS.Core/PLC.cs

@@ -1,4 +1,5 @@
-using System.Net.NetworkInformation;
+using System.Collections.Concurrent;
+using System.Net.NetworkInformation;
 
 namespace WCS.Core;
 
@@ -6,32 +7,126 @@ public class PLC : EntityEx<PLCInfo>
 {
     public PLC(PLCInfo ent, World world) : base(ent)
     {
-        if (Configs.PLCAccessorCreater != null)
-            Accessor = Configs.PLCAccessorCreater.Create(ent);
-        else
-            throw new Exception("Configs.PLCAccessorCreater未赋值");
+        if (Configs.PLCAccessorCreater != null) Accessor = Configs.PLCAccessorCreater.Create(ent);
+        else throw new Exception("Configs.PLCAccessorCreater未赋值");
 
-        Task.Run(() =>
+        IPDetection.AddIP(Entity.IP);
+    }
+
+    public bool Ping { get => IPDetection.GetIpStatus(Entity.IP); }
+
+    public IPLCAccessor Accessor { get; private set; }
+}
+
+public class IPDetection
+{
+    /// <summary>
+    ///  需要检测的IP组,使用线程安全的字典
+    /// </summary>
+    private static ConcurrentDictionary<string, bool> _ipDetection = new ConcurrentDictionary<string, bool>();
+
+    /// <summary>
+    ///  是否启动检测器
+    /// </summary>
+    private static bool isStart = false;
+
+    /// <summary>
+    /// 取消标记,用于停止检测任务
+    /// </summary>
+    private static CancellationTokenSource cancellationTokenSource;
+
+    /// <summary>
+    /// 添加IP进行检测
+    /// </summary>
+    /// <param name="ip"></param>
+    public static void AddIP(string ip)
+    {
+        if (!_ipDetection.ContainsKey(ip))
+        {
+            _ipDetection[ip] = false; // 默认为不在线
+        }
+
+        if (!isStart)
         {
-            while (true)
+            isStart = true;
+            Start();
+        }
+    }
+
+    /// <summary>
+    /// 获取指定IP的状态
+    /// </summary>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    public static bool GetIpStatus(string ip)
+    {
+        return _ipDetection.ContainsKey(ip) && _ipDetection[ip];
+    }
+
+    /// <summary>
+    /// 启动IP检测任务
+    /// </summary>
+    private static void Start()
+    {
+        cancellationTokenSource = new CancellationTokenSource();
+        Task.Run(async () =>
+        {
+            while (!cancellationTokenSource.Token.IsCancellationRequested)
             {
-                Ping = ping();
-                Task.Delay(1000).Wait();
+                await CheckIpsAsync();
+                await Task.Delay(1000); // 等待 1 秒
             }
-            // ReSharper disable once FunctionNeverReturns
-        });
+        }, cancellationTokenSource.Token);
     }
 
-    public bool Ping { get; private set; }
+    /// <summary>
+    /// 停止IP检测任务
+    /// </summary>
+    public static void Stop()
+    {
+        cancellationTokenSource?.Cancel();
+        isStart = false;
+    }
 
-    public IPLCAccessor Accessor { get; private set; }
+    /// <summary>
+    /// 检测所有IP的状态
+    /// </summary>
+    /// <returns></returns>
+    private static async Task CheckIpsAsync()
+    {
+        var tasks = new List<Task>();
 
-    private bool ping(int timeout = 300)
+        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);
+    }
+
+    /// <summary>
+    /// pingIp
+    /// </summary>
+    /// <param name="ip"></param>
+    /// <returns></returns>
+    private static async Task<bool> PingAsync(string ip)
     {
-        var p = new Ping();
-        if (Entity.IP == "1") return false;
-        var res = p.Send(Entity.IP, timeout);
-        return res.Status == IPStatus.Success;
+        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;
+        }
     }
 }