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.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();
/// <summary>
/// 构造函数
@@ -72,20 +74,23 @@ namespace Modbus.Net.Siemens
/// <returns>是否连接成功</returns>
public override async Task<bool> 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<ComConfirmMessageSiemensOutputStruct>();
if (outputStruct == null && ProtocolLinker.IsConnected)
{
ProtocolLinker.Disconnect();
if (outputStruct == null && ProtocolLinker.IsConnected)
{
ProtocolLinker.Disconnect();
}
}
return outputStruct != null;
}

View File

@@ -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();
/// <summary>
/// 构造函数
@@ -143,23 +145,29 @@ namespace Modbus.Net.Siemens
/// <returns>设备是否连接成功</returns>
public override async Task<bool> 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<EstablishAssociationSiemensOutputStruct>();
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<EstablishAssociationSiemensOutputStruct>();
if (outputStruct == null && ProtocolLinker.IsConnected)
{
ProtocolLinker.Disconnect();
}
}
return outputStruct != null;
}

View File

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

View File

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