日常生活的交流与学习

首页 新随笔 联系 管理

secs_learn/Program.cs

此文件是应用程序的入口点,用于配置和启动主机。

  • 使用 Host.CreateDefaultBuilder(args) 创建一个默认配置的主机构建器,自动加载环境变量、配置文件等设置。
  • .ConfigureServices(...) 方法中,通过 services.AddHostedService<DeviceWorker>() 注册 DeviceWorker 类型作为托管服务,这样在主机启动时会自动实例化并运行这个服务。
  • 最后,.Build().Run(); 构建并启动主机,执行注册的服务(在这里即为 DeviceWorker)。整个程序将持续运行,直到被显式停止或遇到不可恢复的错误。
using DeviceWorkerService;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHostedService<DeviceWorker>();
    }).Build().Run();

secs_learn/DeviceWorker.cs

这个文件中定义了一个名为 DeviceWorker 的类,该类继承自 BackgroundService 类,这是 .NET Core 中用于创建长时间运行后台服务的基类。

  • ILogger<DeviceWorker>:注入日志记录器,用于在服务执行过程中输出日志信息。
  • ISecsConnection _hsmsConnection:注入一个实现了 ISecsConnection 接口的对象,它代表了与半导体设备之间的HSMS(High-Speed SECS Message Services)连接。
  • ISecsGem _secsGem:注入一个实现了 ISecsGem 接口的对象,用于提供与遵循GEM规范的设备进行交互的方法。

在构造函数中,设置了 _hsmsConnection.ConnectionChanged 事件处理器,以便当连接状态改变时记录日志信息。

ExecuteAsync 方法是 BackgroundService 的核心方法,在服务启动后会被调用并持续执行,直到收到取消信号或者发生异常。在此方法内:

  • 启动HSMS连接。
  • 使用异步循环等待接收来自设备的主消息(Primary Message)。
  • 对每一个接收到的主消息,构建对应的次消息(Secondary Message)并尝试回复给设备,如果在这个过程中出现异常,则记录错误日志。
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Secs4Net;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace DeviceWorkerService;

internal sealed class DeviceWorker : BackgroundService
{
    private readonly ILogger<DeviceWorker> _logger;
    private readonly ISecsConnection _hsmsConnection;
    private readonly ISecsGem _secsGem;

    public DeviceWorker(ILogger<DeviceWorker> logger, ISecsConnection hsmsConnection, ISecsGem secsGem)
    {
        _logger = logger;
        _hsmsConnection = hsmsConnection;
        _secsGem = secsGem;

        _hsmsConnection.ConnectionChanged += delegate
         {
             switch (_hsmsConnection.State)
             {
                 case ConnectionState.Retry:
                     _logger.LogError($"Connection loss, try to reconnect.");
                     break;
                 case ConnectionState.Connecting:
                 case ConnectionState.Connected:
                     _logger.LogWarning(_hsmsConnection.State.ToString());
                     break;
                 default:
                     _logger.LogInformation($"Connection state = {_hsmsConnection.State}");
                     break;
             }
         };
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            _hsmsConnection.Start(stoppingToken);
            await foreach (var e in _secsGem.GetPrimaryMessageAsync(stoppingToken))
            {
                using var primaryMessage = e.PrimaryMessage;
                _logger.LogInformation($"Received primary message: {primaryMessage}");
                try
                {
                    using var secondaryMessage = new SecsMessage(primaryMessage.S, (byte)(primaryMessage.F + 1))
                    {
                        SecsItem = primaryMessage.SecsItem,
                    };
                    await e.TryReplyAsync(secondaryMessage, stoppingToken);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Exception occurred when processing primary message");
                }
            }
        }
        catch (Exception ex)
        {
            if (stoppingToken.IsCancellationRequested)
            {
                return;
            }
            _logger.LogError(ex, "Unhandled exception occurred on primary messages processing");
        }
    }
}


posted on 2024-01-23 22:31  lazycookie  阅读(192)  评论(0编辑  收藏  举报