diff --git a/Modbus.Net/Modbus.Net.sln b/Modbus.Net/Modbus.Net.sln
index 3199b4c..26be6b5 100644
--- a/Modbus.Net/Modbus.Net.sln
+++ b/Modbus.Net/Modbus.Net.sln
@@ -18,11 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D8DD32FC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.Tests", "..\Tests\Modbus.Net.Tests\Modbus.Net.Tests.csproj", "{3BB01E98-3D45-454A-A1BD-49D7B2C83B74}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.PersistedTests", "..\Tests\Modbus.Net.PersistedTests\Modbus.Net.PersistedTests.csproj", "{EC184EF4-81C4-4A4B-8763-79AC4150E613}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Modbus.Net.Modbus.Test", "Modbus.Net.Modbus.Test\Modbus.Net.Modbus.Test.csproj", "{3615E574-1A98-4BBC-8C08-01FE95AD40AF}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Modbus.Net.Modbus.Test", "..\Samples\Modbus.Net.Modbus.Test\Modbus.Net.Modbus.Test.csproj", "{22A35CA8-CDCF-416D-BA84-08C933B4A3DE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -46,22 +44,17 @@ Global
{3BB01E98-3D45-454A-A1BD-49D7B2C83B74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BB01E98-3D45-454A-A1BD-49D7B2C83B74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BB01E98-3D45-454A-A1BD-49D7B2C83B74}.Release|Any CPU.Build.0 = Release|Any CPU
- {EC184EF4-81C4-4A4B-8763-79AC4150E613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {EC184EF4-81C4-4A4B-8763-79AC4150E613}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {EC184EF4-81C4-4A4B-8763-79AC4150E613}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {EC184EF4-81C4-4A4B-8763-79AC4150E613}.Release|Any CPU.Build.0 = Release|Any CPU
- {3615E574-1A98-4BBC-8C08-01FE95AD40AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3615E574-1A98-4BBC-8C08-01FE95AD40AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {3615E574-1A98-4BBC-8C08-01FE95AD40AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3615E574-1A98-4BBC-8C08-01FE95AD40AF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22A35CA8-CDCF-416D-BA84-08C933B4A3DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22A35CA8-CDCF-416D-BA84-08C933B4A3DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22A35CA8-CDCF-416D-BA84-08C933B4A3DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22A35CA8-CDCF-416D-BA84-08C933B4A3DE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{3BB01E98-3D45-454A-A1BD-49D7B2C83B74} = {D8DD32FC-CF39-4A1A-8FBF-9E82C5278C34}
- {EC184EF4-81C4-4A4B-8763-79AC4150E613} = {D8DD32FC-CF39-4A1A-8FBF-9E82C5278C34}
- {3615E574-1A98-4BBC-8C08-01FE95AD40AF} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
+ {22A35CA8-CDCF-416D-BA84-08C933B4A3DE} = {3597B5C5-45B9-4ECB-92A3-D0FFBE47920A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF00D64E-3C70-474A-8A81-E9E48017C4B5}
diff --git a/Modbus.Net/Modbus.Net/Task/TaskManager.cs b/Modbus.Net/Modbus.Net/Task/TaskManager.cs
deleted file mode 100644
index 8b20615..0000000
--- a/Modbus.Net/Modbus.Net/Task/TaskManager.cs
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * LimitedConcurrencyLevelTaskScheduler类来自于MSDN官方样例,Modbus.Net的作者不保留对这个类的版权。
- * LimitedConcurrencyLevelTaskScheduler class comes from offical samples of MSDN, the author of "Modbus.Net" "donnot" obtain the copyright of LimitedConcurrencyLevelTaskScheduler(only).
- */
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Serilog;
-using Modbus.Net.Interface;
-
-namespace Modbus.Net
-{
- ///
- /// 返回结果的定义类
- ///
- public class DataReturnDef : DataReturnDef
- {
- }
-
- ///
- /// 返回结果的定义类
- ///
- public class DataReturnDef where TMachineKey : IEquatable
- {
- ///
- /// 设备的Id
- ///
- public TMachineKey MachineId { get; set; }
-
- ///
- /// 返回的数据值
- ///
- public Dictionary ReturnValues { get; set; }
- }
-
- ///
- /// Limited concurrency level task scheduler
- ///
- public class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
- {
- ///
- /// Whether the current thread is processing work items.
- ///
- [ThreadStatic] private static bool _currentThreadIsProcessingItems;
-
- ///
- /// The maximum concurrency level allowed by this scheduler.
- ///
- private readonly int _maxDegreeOfParallelism;
-
- ///
- /// The list of tasks to be executed.
- ///
- private readonly LinkedList _tasks = new LinkedList(); // protected by lock(_tasks)
-
- ///
- /// Whether the scheduler is currently processing work items.
- ///
- private int _delegatesQueuedOrRunning; // protected by lock(_tasks)
-
- ///
- /// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the
- /// specified degree of parallelism.
- ///
- ///
- /// The maximum degree of parallelism provided by this scheduler.
- ///
- public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
- {
- if (maxDegreeOfParallelism < 1) throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
- _maxDegreeOfParallelism = maxDegreeOfParallelism;
- }
-
- ///
- /// Gets the maximum concurrency level supported by this scheduler.
- ///
- public sealed override int MaximumConcurrencyLevel
- {
- get { return _maxDegreeOfParallelism; }
- }
-
- ///
- /// Queues a task to the scheduler.
- ///
- ///
- /// The task to be queued.
- ///
- protected sealed override void QueueTask(Task task)
- {
- // Add the task to the list of tasks to be processed. If there aren't enough
- // delegates currently queued or running to process tasks, schedule another.
- lock (_tasks)
- {
- _tasks.AddLast(task);
- if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
- {
- ++_delegatesQueuedOrRunning;
- NotifyThreadPoolOfPendingWork();
- }
- }
- }
-
- ///
- /// Informs the ThreadPool that there's work to be executed for this scheduler.
- ///
- private void NotifyThreadPoolOfPendingWork()
- {
- ThreadPool.UnsafeQueueUserWorkItem(_ =>
- {
- // Note that the current thread is now processing work items.
- // This is necessary to enable inlining of tasks into this thread.
- _currentThreadIsProcessingItems = true;
- try
- {
- // Process all available items in the queue.
- while (true)
- {
- Task item;
- lock (_tasks)
- {
- // When there are no more items to be processed,
- // note that we're done processing, and get out.
- if (_tasks.Count == 0)
- {
- --_delegatesQueuedOrRunning;
- break;
- }
-
- // Get the next item from the queue
- item = _tasks.First.Value;
- _tasks.RemoveFirst();
- }
-
- // Execute the task we pulled out of the queue
- TryExecuteTask(item);
- }
- }
- // We're done processing items on the current thread
- finally
- {
- _currentThreadIsProcessingItems = false;
- }
- }, null);
- }
-
- /// Attempts to execute the specified task on the current thread.
- /// The task to be executed.
- ///
- /// Whether the task could be executed on the current thread.
- protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
- {
- // If this thread isn't already processing a task, we don't support inlining
- if (!_currentThreadIsProcessingItems) return false;
-
- // If the task was previously queued, remove it from the queue
- if (taskWasPreviouslyQueued) TryDequeue(task);
-
- // Try to run the task.
- return TryExecuteTask(task);
- }
-
- ///
- /// Attempts to remove a previously scheduled task from the scheduler.
- ///
- ///
- /// The task to be removed.
- ///
- ///
- /// Whether the task could be found and removed.
- ///
- protected sealed override bool TryDequeue(Task task)
- {
- lock (_tasks)
- {
- return _tasks.Remove(task);
- }
- }
-
- ///
- /// Gets an enumerable of the tasks currently scheduled on this scheduler.
- ///
- ///
- /// An enumerable of the tasks currently scheduled.
- ///
- protected sealed override IEnumerable GetScheduledTasks()
- {
- var lockTaken = false;
- try
- {
- Monitor.TryEnter(_tasks, ref lockTaken);
- if (lockTaken) return _tasks.ToArray();
- else throw new NotSupportedException();
- }
- finally
- {
- if (lockTaken) Monitor.Exit(_tasks);
- }
- }
- }
-
- ///
- /// 具有任务管理的设备
- ///
- /// 设备的Id类型
- public class TaskMachine where TMachineKey : IEquatable
- {
- ///
- /// 任务工厂
- ///
- private readonly TaskFactory _tasks;
-
- ///
- /// 构造函数
- ///
- /// 设备
- /// 任务工厂
- public TaskMachine(IMachineProperty machine, TaskFactory taskFactory)
- {
- Machine = machine;
- _tasks = taskFactory;
- TasksWithTimer = new List();
- }
-
- ///
- /// 设备
- ///
- public IMachineProperty Machine { get; }
-
- ///
- /// 任务调度器
- ///
- public List TasksWithTimer { get; }
-
- ///
- /// 定时方式启动任务
- ///
- /// 任务返回值的类型
- /// 任务
- /// 任务是否执行成功
- public bool InvokeTimer(TaskItem task)
- {
- task.DetectConnected = () => Machine.IsConnected;
- task.GetMachine = () => Machine;
- task.GetTaskFactory = () => _tasks;
-
-
- if (!TasksWithTimer.Exists(taskCon => taskCon.Name == task.Name))
- {
- lock (TasksWithTimer)
- {
- TasksWithTimer.Add(task);
- }
- task.StartTimer();
- return true;
- }
- return false;
- }
-
- ///
- /// 停止任务
- ///
- /// 任务的名称
- /// 是否停止成功
- public bool StopTimer(string taskItemName)
- {
- if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName))
- {
- var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName);
- task?.StopTimer();
- lock (TasksWithTimer)
- {
- TasksWithTimer.Remove(task);
- }
- return true;
- }
- return false;
- }
-
- ///
- /// 停止所有任务
- ///
- /// 是否停止成功
- public bool StopAllTimers()
- {
- var ans = true;
- lock (TasksWithTimer)
- {
- for (int i = 0; i < TasksWithTimer.Count; i++)
- {
- ans = ans && StopTimer(TasksWithTimer[0].Name);
- }
- }
- return ans;
- }
-
- ///
- /// 暂时任务
- ///
- /// 任务的名称
- /// 是否暂停成功
- public bool PauseTimer(string taskItemName)
- {
- if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName))
- {
- var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName);
- task?.StopTimer();
- return true;
- }
- return false;
- }
-
- ///
- /// 暂停所有任务
- ///
- /// 是否暂停成功
- public bool PauseAllTimers()
- {
- var ans = true;
- lock (TasksWithTimer)
- {
- for (int i = 0; i < TasksWithTimer.Count; i++)
- {
- ans = ans && PauseTimer(TasksWithTimer[i].Name);
- }
- }
- return ans;
- }
-
- ///
- /// 恢复任务
- ///
- /// 任务的名称
- /// 是否恢复任务
- public bool ContinueTimer(string taskItemName)
- {
- if (TasksWithTimer.Exists(taskCon => taskCon.Name == taskItemName))
- {
- var task = TasksWithTimer.FirstOrDefault(taskCon => taskCon.Name == taskItemName);
- task?.StartTimer();
- return true;
- }
- return false;
- }
-
- ///
- /// 恢复所有任务
- ///
- /// 是否恢复成功
- public bool ContinueAllTimers()
- {
- var ans = true;
- lock (TasksWithTimer)
- {
- foreach (var task in TasksWithTimer)
- ans = ans && ContinueTimer(task.Name);
- }
- return ans;
- }
-
- ///
- /// 执行任务一次
- ///
- /// 任务返回值的类型
- /// 任务
- /// 任务是否执行成功
- public async Task InvokeOnce(TaskItem task)
- {
- var ans = await task.Invoke(Machine, _tasks, task.Params?.Invoke(), task.TimeoutTime);
- task.Return?.Invoke(ans);
- return true;
- }
- }
-
- internal class TaskMachineEqualityComparer : IEqualityComparer>
- where TKey : IEquatable
- {
- public bool Equals(TaskMachine x, TaskMachine y)
- {
- return x.Machine.Id.Equals(y.Machine.Id);
- }
-
- public int GetHashCode(TaskMachine obj)
- {
- return obj.GetHashCode();
- }
- }
-
- ///
- /// 任务的接口
- ///
- public interface ITaskItem
- {
- ///
- /// 任务的名称
- ///
- string Name { get; set; }
-
- ///
- /// 启动计时器
- ///
- ///
- bool StartTimer();
-
- ///
- /// 停止计时器
- ///
- ///
- bool StopTimer();
- }
-
- ///
- /// 获取数据的预定义任务
- ///
- public class TaskItemGetData : TaskItem
- {
- ///
- /// 构造函数
- ///
- /// 返回值的处理函数
- /// 返回值的键类型
- /// 任务的超时时间
- /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串
- public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int timeout = 100000, string reName = null)
- {
- Name = reName ?? "GetDatas";
- TimeoutTime = timeout;
- Invoke = async (machine, tasks, parameters, timeoutTime) =>
- {
- var cts = new CancellationTokenSource();
- cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime));
- try
- {
- var ans =
- await tasks.StartNew(
- async () => await machine.GetMachineMethods()
- .GetDatasAsync(
- getDataType).WithCancellation(cts.Token)).Unwrap();
- return new DataReturnDef
- {
- MachineId = machine.GetMachineIdString(),
- ReturnValues = ans
- };
- }
- catch (Exception e)
- {
- Log.Error(e, "GetData task has been canceled.");
- machine.Disconnect();
- }
- return null;
-
- };
- Params = null;
- Return = returnFunc;
- }
-
- ///
- /// 构造函数
- ///
- /// 返回值的处理函数
- /// 返回值的键类型
- /// 循环间隔(毫秒)
- /// 设备离线时的循环间隔(毫秒)
- /// 任务的超时时间
- /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串
- public TaskItemGetData(Action returnFunc, MachineGetDataType getDataType, int getCycle,
- int sleepCycle, int timeout = 100000, string reName = null) : this(returnFunc, getDataType, timeout, reName)
- {
- TimerDisconnectedTime = sleepCycle;
- TimerTime = getCycle;
- }
- }
-
- ///
- /// 写入数据的预定义任务
- ///
- public class TaskItemSetData : TaskItem
- {
- ///
- /// 构造函数
- ///
- /// 写入的值
- /// 写入值的键类型
- /// 返回值的处理函数
- /// 任务的超时时间
- /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串
- public TaskItemSetData(Func> values, MachineSetDataType setDataType, int timeout = 100000, Action returnFunc = null, string reName = null)
- {
- Name = reName ?? "SetDatas";
- TimeoutTime = timeout;
- Invoke = async (machine, tasks, parameters, timeoutTime) =>
- {
- var cts = new CancellationTokenSource();
- cts.CancelAfter(TimeSpan.FromMilliseconds(timeoutTime));
- try
- {
- var ans =
- await tasks.StartNew(
- async () => await machine.GetMachineMethods().
- SetDatasAsync(setDataType, (Dictionary)parameters[0]
- ).WithCancellation(cts.Token)).Unwrap();
- return ans;
- }
- catch (Exception e)
- {
- Log.Error(e, "SetData task has been canceled.");
- machine.Disconnect();
- }
- return false;
- };
- Params = () => new object[] {values()};
- Return = returnFunc;
- }
-
- ///
- /// 构造函数
- ///
- /// 写入的值
- /// 写入值的键类型
- /// 返回值的处理函数
- /// 循环间隔(毫秒)
- /// 设备离线时的循环间隔(毫秒)
- /// 任务的超时时间
- /// 重命名,对单个设备使用多个GetData时必须填写不同的字符串
- public TaskItemSetData(Func> values, MachineSetDataType setDataType, int getCycle,
- int sleepCycle, int timeout = 100000, Action returnFunc = null, string reName = null)
- : this(values, setDataType, timeout, returnFunc, reName)
- {
- TimerDisconnectedTime = sleepCycle;
- TimerTime = getCycle;
- }
- }
-
- ///
- /// 任务
- ///
- /// 任务返回值的类型
- public class TaskItem : ITaskItem, IEquatable>
- {
- ///
- /// 定时器
- ///
- private Timer Timer { get; set; }
-
- ///
- /// 定时器的时间
- ///
- public int TimerTime { get; set; }
-
- ///
- /// 超时时间
- ///
- public int TimeoutTime { get; set; } = 100000;
-
- ///
- /// 离线定时器
- ///
- private Timer TimerDisconnected { get; set; }
-
- ///
- /// 离线定时器的时间
- ///
- public int TimerDisconnectedTime { get; set; }
-
- ///
- /// 执行的任务
- ///
- public Func> Invoke { get; set; }
-
- ///
- /// 检测设备的在线状态
- ///
- internal Func DetectConnected { get; set; }
-
- ///
- /// 任务执行的参数
- ///
- public Func