2018-01-04 Update 1 Add Siemens Connection AsyncLock

This commit is contained in:
parallelbgls
2018-01-04 12:42:58 +08:00
parent e9b41eb06a
commit 0fcd6266d4
4 changed files with 51 additions and 34 deletions

View File

@@ -1,5 +1,6 @@
using System.Configuration; using System.Configuration;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {
@@ -9,6 +10,7 @@ namespace Modbus.Net.Siemens
public class SiemensPpiProtocol : SiemensProtocol public class SiemensPpiProtocol : SiemensProtocol
{ {
private readonly string _com; private readonly string _com;
private readonly AsyncLock _lock = new AsyncLock();
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
@@ -72,20 +74,23 @@ namespace Modbus.Net.Siemens
/// <returns>是否连接成功</returns> /// <returns>是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
if (ProtocolLinker.IsConnected) return true; IOutputStruct outputStruct;
if (!await ProtocolLinker.ConnectAsync()) return false; using (await _lock.LockAsync())
var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress); {
var outputStruct = if (ProtocolLinker.IsConnected) return true;
if (!await ProtocolLinker.ConnectAsync()) return false;
var inputStruct = new ComCreateReferenceSiemensInputStruct(SlaveAddress, MasterAddress);
outputStruct =
(await (await (await (await
ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocol)], ForceSendReceiveAsync(this[typeof(ComCreateReferenceSiemensProtocol)],
inputStruct)). inputStruct)).SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer =>
SendReceiveAsync(this[typeof(ComConfirmMessageSiemensProtocol)], answer => answer != null
answer != null
? new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress) ? new ComConfirmMessageSiemensInputStruct(SlaveAddress, MasterAddress)
: null)).Unwrap<ComConfirmMessageSiemensOutputStruct>(); : null)).Unwrap<ComConfirmMessageSiemensOutputStruct>();
if (outputStruct == null && ProtocolLinker.IsConnected) if (outputStruct == null && ProtocolLinker.IsConnected)
{ {
ProtocolLinker.Disconnect(); ProtocolLinker.Disconnect();
}
} }
return outputStruct != null; return outputStruct != null;
} }

View File

@@ -1,5 +1,6 @@
using System.Configuration; using System.Configuration;
using System.Threading.Tasks; using System.Threading.Tasks;
using Nito.AsyncEx;
namespace Modbus.Net.Siemens namespace Modbus.Net.Siemens
{ {
@@ -17,6 +18,7 @@ namespace Modbus.Net.Siemens
private readonly byte _tdpuSize; private readonly byte _tdpuSize;
private readonly ushort _tsapDst; private readonly ushort _tsapDst;
private int _connectTryCount; private int _connectTryCount;
private readonly AsyncLock _lock = new AsyncLock();
/// <summary> /// <summary>
/// 构造函数 /// 构造函数
@@ -143,23 +145,29 @@ namespace Modbus.Net.Siemens
/// <returns>设备是否连接成功</returns> /// <returns>设备是否连接成功</returns>
public override async Task<bool> ConnectAsync() public override async Task<bool> ConnectAsync()
{ {
_connectTryCount++; IOutputStruct outputStruct;
if (ProtocolLinker.IsConnected) return true; using (await _lock.LockAsync())
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<EstablishAssociationSiemensOutputStruct>();
if (outputStruct == null && ProtocolLinker.IsConnected)
{ {
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<EstablishAssociationSiemensOutputStruct>();
if (outputStruct == null && ProtocolLinker.IsConnected)
{
ProtocolLinker.Disconnect();
}
} }
return outputStruct != null; return outputStruct != null;
} }

View File

@@ -401,9 +401,10 @@ namespace Modbus.Net
/// <param name="returnFunc">返回值的处理函数</param> /// <param name="returnFunc">返回值的处理函数</param>
/// <param name="getDataType">返回值的键类型</param> /// <param name="getDataType">返回值的键类型</param>
/// <param name="timeout">任务的超时时间</param> /// <param name="timeout">任务的超时时间</param>
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int timeout = 100000) /// <param name="reName">重命名对单个设备使用多个GetData时必须填写不同的字符串</param>
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int timeout = 100000, string reName = null)
{ {
Name = "GetDatas"; Name = reName ?? "GetDatas";
TimeoutTime = timeout; TimeoutTime = timeout;
Invoke = async (machine, tasks, parameters, timeoutTime) => Invoke = async (machine, tasks, parameters, timeoutTime) =>
{ {
@@ -442,8 +443,9 @@ namespace Modbus.Net
/// <param name="getCycle">循环间隔(毫秒)</param> /// <param name="getCycle">循环间隔(毫秒)</param>
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param> /// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
/// <param name="timeout">任务的超时时间</param> /// <param name="timeout">任务的超时时间</param>
/// <param name="reName">重命名对单个设备使用多个GetData时必须填写不同的字符串</param>
public TaskItemGetData(Action<DataReturnDef> returnFunc, MachineGetDataType getDataType, int getCycle, public TaskItemGetData(Action<DataReturnDef> 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; TimerDisconnectedTime = sleepCycle;
TimerTime = getCycle; TimerTime = getCycle;
@@ -462,9 +464,10 @@ namespace Modbus.Net
/// <param name="setDataType">写入值的键类型</param> /// <param name="setDataType">写入值的键类型</param>
/// <param name="returnFunc">返回值的处理函数</param> /// <param name="returnFunc">返回值的处理函数</param>
/// <param name="timeout">任务的超时时间</param> /// <param name="timeout">任务的超时时间</param>
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int timeout = 100000, Action<bool> returnFunc = null) /// <param name="reName">重命名对单个设备使用多个GetData时必须填写不同的字符串</param>
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int timeout = 100000, Action<bool> returnFunc = null, string reName = null)
{ {
Name = "SetDatas"; Name = reName ?? "SetDatas";
TimeoutTime = timeout; TimeoutTime = timeout;
Invoke = async (machine, tasks, parameters, timeoutTime) => Invoke = async (machine, tasks, parameters, timeoutTime) =>
{ {
@@ -499,9 +502,10 @@ namespace Modbus.Net
/// <param name="getCycle">循环间隔(毫秒)</param> /// <param name="getCycle">循环间隔(毫秒)</param>
/// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param> /// <param name="sleepCycle">设备离线时的循环间隔(毫秒)</param>
/// <param name="timeout">任务的超时时间</param> /// <param name="timeout">任务的超时时间</param>
/// <param name="reName">重命名对单个设备使用多个GetData时必须填写不同的字符串</param>
public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int getCycle, public TaskItemSetData(Func<Dictionary<string, double>> values, MachineSetDataType setDataType, int getCycle,
int sleepCycle, int timeout = 100000, Action<bool> returnFunc = null) int sleepCycle, int timeout = 100000, Action<bool> returnFunc = null, string reName = null)
: this(values, setDataType, timeout, returnFunc) : this(values, setDataType, timeout, returnFunc, reName)
{ {
TimerDisconnectedTime = sleepCycle; TimerDisconnectedTime = sleepCycle;
TimerTime = getCycle; TimerTime = getCycle;

View File

@@ -303,7 +303,7 @@ namespace Modbus.Net
{ {
if (_socketClient.Connected) if (_socketClient.Connected)
{ {
_socketClient?.GetStream().Dispose(); _socketClient.GetStream().Dispose();
} }
_socketClient?.Close(); _socketClient?.Close();
} }