From 0fcd6266d466e631a656086840747acf220543b6 Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Thu, 4 Jan 2018 12:42:58 +0800 Subject: [PATCH] 2018-01-04 Update 1 Add Siemens Connection AsyncLock --- .../Modbus.Net.Siemens/SiemensPpiProtocol.cs | 25 +++++++----- .../Modbus.Net.Siemens/SiemensTcpProtocol.cs | 40 +++++++++++-------- Modbus.Net/Modbus.Net/TaskManager.cs | 18 +++++---- Modbus.Net/Modbus.Net/TcpConnector.cs | 2 +- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs index b25bb07..0c275eb 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensPpiProtocol.cs @@ -1,5 +1,6 @@ using System.Configuration; using System.Threading.Tasks; +using Nito.AsyncEx; namespace Modbus.Net.Siemens { @@ -9,6 +10,7 @@ namespace Modbus.Net.Siemens public class SiemensPpiProtocol : SiemensProtocol { private readonly string _com; + private readonly AsyncLock _lock = new AsyncLock(); /// /// 构造函数 @@ -72,20 +74,23 @@ namespace Modbus.Net.Siemens /// 是否连接成功 public override async Task ConnectAsync() { - if (ProtocolLinker.IsConnected) return true; - if (!await ProtocolLinker.ConnectAsync()) return false; - var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress); - var outputStruct = + IOutputStruct outputStruct; + using (await _lock.LockAsync()) + { + if (ProtocolLinker.IsConnected) return true; + if (!await ProtocolLinker.ConnectAsync()) return false; + var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress); + outputStruct = (await (await ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocol)], - inputStruct)). - SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer => - answer != null + inputStruct)).SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer => + answer != null ? new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress) : null)).Unwrap(); - if (outputStruct == null && ProtocolLinker.IsConnected) - { - ProtocolLinker.Disconnect(); + if (outputStruct == null && ProtocolLinker.IsConnected) + { + ProtocolLinker.Disconnect(); + } } return outputStruct != null; } diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs index ed24709..f98974b 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensTcpProtocol.cs @@ -1,5 +1,6 @@ using System.Configuration; using System.Threading.Tasks; +using Nito.AsyncEx; namespace Modbus.Net.Siemens { @@ -17,6 +18,7 @@ namespace Modbus.Net.Siemens private readonly byte _tdpuSize; private readonly ushort _tsapDst; private int _connectTryCount; + private readonly AsyncLock _lock = new AsyncLock(); /// /// 构造函数 @@ -143,23 +145,29 @@ namespace Modbus.Net.Siemens /// 设备是否连接成功 public override async Task ConnectAsync() { - _connectTryCount++; - if (ProtocolLinker.IsConnected) return true; - if (!await ProtocolLinker.ConnectAsync()) return false; - _connectTryCount = 0; - var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); - var outputStruct = - //先建立连接,然后建立设备的引用 - (await (await - ForceSendReceiveAsync(this[typeof(CreateReferenceSiemensProtocol)], inputStruct)).SendReceiveAsync( - this[typeof(EstablishAssociationSiemensProtocol)], answer => - answer != null ? - new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling, - _maxCalled, - _maxPdu) : null)).Unwrap(); - if (outputStruct == null && ProtocolLinker.IsConnected) + IOutputStruct outputStruct; + using (await _lock.LockAsync()) { - ProtocolLinker.Disconnect(); + _connectTryCount++; + if (ProtocolLinker.IsConnected) return true; + if (!await ProtocolLinker.ConnectAsync()) return false; + _connectTryCount = 0; + var inputStruct = new CreateReferenceSiemensInputStruct(_tdpuSize, _taspSrc, _tsapDst); + outputStruct = + //先建立连接,然后建立设备的引用 + (await (await + ForceSendReceiveAsync(this[typeof(CreateReferenceSiemensProtocol)], inputStruct)) + .SendReceiveAsync( + this[typeof(EstablishAssociationSiemensProtocol)], answer => + answer != null + ? new EstablishAssociationSiemensInputStruct(0x0101, _maxCalling, + _maxCalled, + _maxPdu) + : null)).Unwrap(); + if (outputStruct == null && ProtocolLinker.IsConnected) + { + ProtocolLinker.Disconnect(); + } } return outputStruct != null; } diff --git a/Modbus.Net/Modbus.Net/TaskManager.cs b/Modbus.Net/Modbus.Net/TaskManager.cs index aeceeee..06a631e 100644 --- a/Modbus.Net/Modbus.Net/TaskManager.cs +++ b/Modbus.Net/Modbus.Net/TaskManager.cs @@ -401,9 +401,10 @@ namespace Modbus.Net /// 返回值的处理函数 /// 返回值的键类型 /// 任务的超时时间 - public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int timeout = 100000) + /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串 + public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int timeout = 100000, string reName = null) { - Name = "GetDatas"; + Name = reName ?? "GetDatas"; TimeoutTime = timeout; Invoke = async (machine, tasks, parameters, timeoutTime) => { @@ -442,8 +443,9 @@ namespace Modbus.Net /// 循环间隔(毫秒) /// 设备离线时的循环间隔(毫秒) /// 任务的超时时间 + /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串 public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle, - int sleepCycle, int timeout = 100000) : this(returnFunc, getDataType, timeout) + int sleepCycle, int timeout = 100000, string reName = null) : this(returnFunc, getDataType, timeout, reName) { TimerDisconnectedTime = sleepCycle; TimerTime = getCycle; @@ -462,9 +464,10 @@ namespace Modbus.Net /// 写入值的键类型 /// 返回值的处理函数 /// 任务的超时时间 - public TaskItemSetData(Func> values, MachineSetDataType setDataType, int timeout = 100000, Action returnFunc = null) + /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串 + public TaskItemSetData(Func> values, MachineSetDataType setDataType, int timeout = 100000, Action returnFunc = null, string reName = null) { - Name = "SetDatas"; + Name = reName ?? "SetDatas"; TimeoutTime = timeout; Invoke = async (machine, tasks, parameters, timeoutTime) => { @@ -499,9 +502,10 @@ namespace Modbus.Net /// 循环间隔(毫秒) /// 设备离线时的循环间隔(毫秒) /// 任务的超时时间 + /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串 public TaskItemSetData(Func> values, MachineSetDataType setDataType, int getCycle, - int sleepCycle, int timeout = 100000, Action returnFunc = null) - : this(values, setDataType, timeout, returnFunc) + int sleepCycle, int timeout = 100000, Action returnFunc = null, string reName = null) + : this(values, setDataType, timeout, returnFunc, reName) { TimerDisconnectedTime = sleepCycle; TimerTime = getCycle; diff --git a/Modbus.Net/Modbus.Net/TcpConnector.cs b/Modbus.Net/Modbus.Net/TcpConnector.cs index f6ee3f7..4cb6248 100644 --- a/Modbus.Net/Modbus.Net/TcpConnector.cs +++ b/Modbus.Net/Modbus.Net/TcpConnector.cs @@ -303,7 +303,7 @@ namespace Modbus.Net { if (_socketClient.Connected) { - _socketClient?.GetStream().Dispose(); + _socketClient.GetStream().Dispose(); } _socketClient?.Close(); }