107 lines
4.2 KiB
C#
107 lines
4.2 KiB
C#
using Cowain.Base.Helpers;
|
||
using Plugin.Cowain.Driver.ViewModels;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Plugin.Cowain.Driver.Abstractions;
|
||
using Plugin.Cowain.Driver.IServices;
|
||
using Microsoft.Extensions.Logging;
|
||
|
||
namespace Plugin.Cowain.Driver;
|
||
|
||
|
||
/// <summary>
|
||
/// 设备数据采集,不注入到容器,一个设备一个线程
|
||
/// </summary>
|
||
public class DeviceThread
|
||
{
|
||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); // 初始化计数为1,最大计数也为1,实现互斥
|
||
private Task? _mainTask;
|
||
private Task? _consumeVariablesTask;
|
||
private readonly IDriver _driver;
|
||
private readonly DeviceViewModel _device;
|
||
private readonly IActionPluginService _actionPluginService;
|
||
private IServiceProvider _serviceProvider;
|
||
private IVariableChannelService? _variableChannelService;
|
||
private readonly ILogger<DeviceThread> _logger;
|
||
public DeviceViewModel Device { get => _device; }
|
||
|
||
public IDriver Driver { get => _driver; }
|
||
|
||
public DeviceThread(IDriver driver, IActionPluginService actionPluginService, IServiceProvider serviceProvider, DeviceViewModel device)
|
||
{
|
||
_serviceProvider = serviceProvider;
|
||
_driver = driver;
|
||
_actionPluginService = actionPluginService;
|
||
_device = device;
|
||
_variableChannelService = _serviceProvider.GetService<IVariableChannelService>();
|
||
_logger = ServiceLocator.GetRequiredService<ILogger<DeviceThread>>();
|
||
}
|
||
|
||
|
||
public async Task StartReadAsync(CancellationToken cancellationToken)
|
||
{
|
||
if (!_device.Enable)
|
||
{
|
||
return;
|
||
}
|
||
_logger.LogInformation($"DeviceThread线程自动启动:{_device.DeviceName}");
|
||
await _semaphore.WaitAsync(cancellationToken);
|
||
_variableChannelService?.RegisterDeviceActions(_device);
|
||
//消费变量,但不等待结果
|
||
_consumeVariablesTask = _variableChannelService?.ConsumeVariablesAsync();
|
||
_mainTask = Task.Factory.StartNew(async () =>
|
||
{
|
||
_driver.SetParam(_device.Param);
|
||
_driver.SetDeviceModel(_device);
|
||
var connect = await _driver.OpenAsync();
|
||
if (!connect)
|
||
{
|
||
//建立过链接后就不用再连接了
|
||
_logger.LogInformation($"DeviceThread设备连接失败:{_device.DeviceName}");
|
||
}
|
||
await _driver.ReadThreadAsync(_device, cancellationToken);
|
||
|
||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap();
|
||
//释放信号量,允许其他线程进入
|
||
_semaphore.Release();
|
||
}
|
||
|
||
public async Task StopReadAsync(CancellationToken cancellationToken)
|
||
{
|
||
_logger.LogInformation($"DeviceThread线程停止开始:{_device.DeviceName}");
|
||
_variableChannelService?.StopConsumeVariablesAsync(cancellationToken);
|
||
try
|
||
{
|
||
// 等待消费变量任务完成
|
||
_logger.LogInformation($"DeviceThread 消费变量任务判断:{_device.DeviceName}");
|
||
if (_consumeVariablesTask != null && !_consumeVariablesTask.IsCompleted)
|
||
{
|
||
_logger.LogInformation($"DeviceThread 消费变量任务await:{_device.DeviceName}");
|
||
await Task.WhenAny(_consumeVariablesTask, Task.Delay(Timeout.Infinite, cancellationToken));
|
||
}
|
||
// 等待主任务完成
|
||
_logger.LogInformation($"DeviceThread 主任务判断:{_device.DeviceName}");
|
||
if (_mainTask != null && !_mainTask.IsCompleted)
|
||
{
|
||
_logger.LogInformation($"DeviceThread 主任务await:{_device.DeviceName}");
|
||
await Task.WhenAny(_mainTask, Task.Delay(Timeout.Infinite, cancellationToken));
|
||
}
|
||
}
|
||
catch (OperationCanceledException ex)
|
||
{
|
||
_logger.LogInformation($"DeviceThread-StopReadAsync任务取消:{_device.DeviceName}->{ex.Message}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, $"DeviceThread-StopReadAsync任务异常:{_device.DeviceName}");
|
||
}
|
||
finally
|
||
{
|
||
// 确保资源释放
|
||
_driver.Close();
|
||
_logger.LogInformation($"DeviceThread线程停止完成:{_device.DeviceName}");
|
||
}
|
||
}
|
||
|
||
|
||
}
|