Files
WCS/Plugins/Driver/Cowain.Driver/DeviceThread.cs
2026-03-02 09:08:20 +08:00

107 lines
4.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}");
}
}
}