using System; using System.Threading; using System.Threading.Tasks; using S7.Net; // 确保引用 S7.Net 库 namespace RIZO.Service.PLC { public class PlcService : IDisposable { private Plc _plc; private readonly string _ipAddress; private readonly CpuType _cpuType; private readonly short _rack; private readonly short _slot; private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private bool _disposed; public PlcService(string ipAddress, CpuType cpuType = CpuType.S71200, short rack = 0, short slot = 1) { _ipAddress = ipAddress; _cpuType = cpuType; _rack = rack; _slot = slot; } private async Task ConnectAsync(CancellationToken cancellationToken = default) { int maxRetries = 3; int retryDelayMs = 2000; int attempt = 0; while (attempt < maxRetries) { attempt++; try { _plc = new Plc(_cpuType, _ipAddress, _rack, _slot); await Task.Run(() => _plc.Open(), cancellationToken); // 在线程池中执行同步Open Console.WriteLine($"成功连接到PLC: {_ipAddress} (尝试{attempt}/{maxRetries})"); return; } catch (Exception ex) { Console.WriteLine($"连接尝试 {attempt}/{maxRetries} 失败: {ex.Message}"); if (attempt < maxRetries) { Console.WriteLine($"{retryDelayMs / 1000}秒后重试..."); await Task.Delay(retryDelayMs, cancellationToken); } else { Console.WriteLine("无法建立PLC连接,请检查网络和设备状态"); _plc?.Close(); _plc = null; } } } } public async Task ReadAsync(string address, CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken); try { if (_plc == null || !_plc.IsConnected) { await ConnectAsync(cancellationToken); if (_plc == null || !_plc.IsConnected) throw new InvalidOperationException("PLC未连接"); } return await Task.Run(() => _plc.Read(address), cancellationToken); } catch (Exception ex) { Console.WriteLine($"Read error: {ex.Message}"); return null; } finally { _semaphore.Release(); } } public async Task WriteAsync(string address, object value, CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken); try { if (_plc == null || !_plc.IsConnected) { await ConnectAsync(cancellationToken); if (_plc == null || !_plc.IsConnected) throw new InvalidOperationException("PLC未连接"); } await Task.Run(() => _plc.Write(address, value), cancellationToken); } catch (Exception ex) { Console.WriteLine($"Write error: {ex.Message}"); } finally { _semaphore.Release(); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { _semaphore.Dispose(); _plc?.Close(); (_plc as IDisposable)?.Dispose(); } _disposed = true; } } }