From b019269bd753bfa9c2c8fa55def37a34073e767c Mon Sep 17 00:00:00 2001 From: "David P.G" Date: Sat, 5 Jul 2025 15:38:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=B8=BA=E5=9C=A8=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E7=9A=84=E7=BA=BF=E7=A8=8B=E4=B8=8A=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Services/S7BackgroundService.cs | 70 +++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/Services/S7BackgroundService.cs b/Services/S7BackgroundService.cs index 4e9c2f1..bda4ac5 100644 --- a/Services/S7BackgroundService.cs +++ b/Services/S7BackgroundService.cs @@ -18,7 +18,9 @@ namespace PMSWPF.Services private readonly ILogger _logger; private readonly DataServices _dataServices; private readonly Dictionary _s7PlcClients = new Dictionary(); - + private Thread _pollingThread; + private CancellationTokenSource _cancellationTokenSource; + private readonly Dictionary _pollingIntervals = new Dictionary { { PollLevelType.TenMilliseconds, TimeSpan.FromMilliseconds((int)PollLevelType.TenMilliseconds) }, @@ -54,10 +56,23 @@ namespace PMSWPF.Services _logger.LogInformation("设备列表已更改。S7客户端可能需要重新初始化。"); } - protected override async Task ExecuteAsync(CancellationToken stoppingToken) + protected override Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("S7后台服务正在启动。"); + _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); + _pollingThread = new Thread(() => PollingLoop(_cancellationTokenSource.Token)) + { + IsBackground = true + }; + _pollingThread.Start(); + + return Task.CompletedTask; + } + + private void PollingLoop(CancellationToken stoppingToken) + { + _logger.LogInformation("S7轮询线程已启动。"); stoppingToken.Register(() => _logger.LogInformation("S7后台服务正在停止。")); _s7Devices = _dataServices.Devices?.Where(d => d.ProtocolType == ProtocolType.S7 && d.IsActive) @@ -65,21 +80,22 @@ namespace PMSWPF.Services while (!stoppingToken.IsCancellationRequested) { - _logger.LogDebug("S7后台服务正在执行后台工作。"); - - await PollS7Devices(stoppingToken); - + // _logger.LogDebug("S7后台服务正在执行后台工作。"); + PollS7Devices(stoppingToken); + // 短暂休眠以防止CPU占用过高 + Thread.Sleep(100); } - _logger.LogInformation("S7后台服务已停止。"); + _logger.LogInformation("S7轮询线程已停止。"); } + /// /// 初始化或重新连接PLC客户端 /// /// S7设备 /// 连接成功的Plc客户端实例,如果连接失败则返回null - private async Task InitializePlcClient(Device device) + private Plc? InitializePlcClient(Device device) { // 检查字典中是否已存在该设备的PLC客户端 if (!_s7PlcClients.TryGetValue(device.Id, out var plcClient)) @@ -88,7 +104,7 @@ namespace PMSWPF.Services try { plcClient = new Plc(device.CpuType, device.Ip, (short)device.Prot, device.Rack, device.Slot); - await plcClient.OpenAsync(); // 尝试打开连接 + plcClient.Open(); // 尝试打开连接 _s7PlcClients[device.Id] = plcClient; // 将新创建的客户端添加到字典 _logger.LogInformation($"已连接到S7 PLC: {device.Name} ({device.Ip})"); } @@ -103,7 +119,7 @@ namespace PMSWPF.Services // 如果存在但未连接,则尝试重新连接 try { - await plcClient.OpenAsync(); // 尝试重新打开连接 + plcClient.Open(); // 尝试重新打开连接 _logger.LogInformation($"已重新连接到S7 PLC: {device.Name} ({device.Ip})"); } catch (Exception ex) @@ -119,12 +135,21 @@ namespace PMSWPF.Services /// 轮询S7设备数据 /// /// 取消令牌 - private async Task PollS7Devices(CancellationToken stoppingToken) + private void PollS7Devices(CancellationToken stoppingToken) { if (_s7Devices == null || !_s7Devices.Any()) { _logger.LogDebug("未找到活跃的S7设备进行轮询。等待5秒后重试。"); - await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); + try + { + // 使用CancellationToken来使等待可取消 + Task.Delay(TimeSpan.FromSeconds(5), stoppingToken).Wait(stoppingToken); + } + catch (OperationCanceledException) + { + // 如果在等待期间取消,则退出 + return; + } return; } @@ -133,7 +158,7 @@ namespace PMSWPF.Services if (stoppingToken.IsCancellationRequested) return; // 尝试获取或初始化PLC客户端连接 - var plcClient = await InitializePlcClient(device); + var plcClient = InitializePlcClient(device); if (plcClient == null) { continue; // 如果连接失败,则跳过当前设备 @@ -141,7 +166,7 @@ namespace PMSWPF.Services // 读取设备变量 - await ReadDeviceVariables(plcClient, device, stoppingToken); + ReadDeviceVariables(plcClient, device, stoppingToken); } } @@ -152,7 +177,7 @@ namespace PMSWPF.Services /// 已连接的Plc客户端实例。 /// S7设备。 /// 取消令牌。 - private async Task ReadDeviceVariables(Plc plcClient, Device device, CancellationToken stoppingToken) + private void ReadDeviceVariables(Plc plcClient, Device device, CancellationToken stoppingToken) { // 过滤出当前设备和S7协议相关的变量 var s7Variables = device.VariableTables @@ -168,7 +193,6 @@ namespace PMSWPF.Services try { - Stopwatch sw = Stopwatch.StartNew(); // 遍历并读取每个S7变量 foreach (var variable in s7Variables) { @@ -180,6 +204,7 @@ namespace PMSWPF.Services _logger.LogWarning($"未知轮询级别 {variable.PollLevelType},跳过变量 {variable.Name}。"); continue; } + Thread.Sleep(100); // 检查是否达到轮询时间 if ((DateTime.Now - variable.LastPollTime) < interval) @@ -190,14 +215,14 @@ namespace PMSWPF.Services try { // 从PLC读取变量值 - var value = await plcClient.ReadAsync(variable.S7Address); + var value = plcClient.Read(variable.S7Address); if (value != null) { // 更新变量的原始数据值和显示值 variable.DataValue = value.ToString(); variable.DisplayValue = SiemensHelper.ConvertS7Value(value, variable.DataType, variable.Converstion); variable.LastPollTime = DateTime.Now; // 更新最后轮询时间 - _logger.LogDebug($"已读取变量 {variable.Name}: {variable.DataValue}"); + _logger.LogDebug($"线程ID:{Environment.CurrentManagedThreadId},已读取变量 {variable.Name}: {variable.DataValue}"); } } catch (Exception ex) @@ -206,8 +231,6 @@ namespace PMSWPF.Services } } - sw.Stop(); - _logger.LogInformation($"从: {device.Name} ({device.Ip})读取变量总耗时:{sw.ElapsedMilliseconds}ms"); } catch (Exception ex) { @@ -219,6 +242,11 @@ namespace PMSWPF.Services { _logger.LogInformation("S7 Background Service is stopping."); + // Signal the polling thread to stop + _cancellationTokenSource?.Cancel(); + // Wait for the polling thread to finish + _pollingThread?.Join(); + // Close all active PLC connections foreach (var plcClient in _s7PlcClients.Values) { @@ -234,4 +262,4 @@ namespace PMSWPF.Services await base.StopAsync(stoppingToken); } } -} \ No newline at end of file +}