怪奇物语

怪奇物语

首页 新随笔 联系 管理

wpf项目中使用host background service

App.xaml.cs

using System;
using System.Windows;
using SecsDemo.Application.DependencyInjection;
using SecsDemo.Automation.ViewModels;
using SecsDemo.Automation.Views;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;

namespace SecsDemo.Automation;

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : System.Windows.Application
{
    public IHost AppHost { get; private set; } = ConfigureServices();

    /// <summary>
    /// Gets the current <see cref="App"/> instance in use
    /// </summary>
    public static new App Current => (App)System.Windows.Application.Current;

    /// <summary>
    /// Application Entry for SecsDemoCoc
    /// </summary>
    public App()
    {
        
    }

    private static IHost ConfigureServices()
    {
        // 使用 HostApplicationBuilder 创建主机,整合依赖注入和服务配置
        HostApplicationBuilder hostApplicationBuilder = Host.CreateApplicationBuilder();
        hostApplicationBuilder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        hostApplicationBuilder.Services.AddSecsGemServices(hostApplicationBuilder.Configuration);
        

        hostApplicationBuilder.Services.AddLogging(loggingBuilder =>
        {
            loggingBuilder.ClearProviders();
            loggingBuilder.SetMinimumLevel(LogLevel.Debug);
            loggingBuilder.AddNLog(hostApplicationBuilder.Configuration);
        });

        hostApplicationBuilder.Services.AddTransient<MainViewModel>();
        hostApplicationBuilder.Services.AddTransient<MainView>(sp => new MainView { DataContext = sp.GetService<MainViewModel>() });

        return hostApplicationBuilder.Build();
    }

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        AppHost.Start();
        var mainViewModel = new MainView { DataContext = Activator.CreateInstance<MainViewModel>() };
        var mainWindow = AppHost.Services.GetRequiredService<MainView>();
        mainWindow.DataContext = mainViewModel;
        mainWindow.Show();
    }
}

App.xaml

<Application x:Class="SecsDemo.Automation.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="Application_Startup">
    <Application.Resources />
</Application>

SecsGemServiceExtensions.cs


using System.Reflection;
using SecsDemo.Application.SecsHandler;
using SecsDemo.Application.SecsManager;
using SecsDemo.Application.SecsSender;
using SecsDemo.Application.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using Secs4Net;

namespace SecsDemo.Application.DependencyInjection;

public static class SecsGemServiceExtensions
{
    public static void AddSecsGemServices(this IServiceCollection collection, IConfigurationRoot configurationRoot)
    {
        // 添加SECS服务
        Console.WriteLine(configurationRoot.GetSection("Secs4net"));
        collection.Configure<SecsGemOptions>(configurationRoot.GetSection("Secs4net"));
        collection.AddSingleton<ISecsConnection, HsmsConnection>();
        collection.AddSingleton<ISecsGem, SecsGem>();
        collection.AddSingleton<ISecsGemLogger, DeviceLogger>();
        collection.AddHostedService<SecsBackgroundService>();
        collection.AddTransient<ISecsMessageHandler, SecsMessageHandler>();

    }
}

SecsBackgroundService.cs


using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Secs4Net;


namespace SecsDemo.Application.Services;

public class SecsBackgroundService : BackgroundService
{
    private readonly ILogger<SecsBackgroundService> _logger;
    private readonly ISecsConnection _secsConnection;
    private readonly ISecsGem _secsGem;
    private readonly IEnumerable<ISecsMessageHandler> _messageHandlers;

    public SecsBackgroundService(ILogger<SecsBackgroundService> logger, ISecsConnection secsConnection, ISecsGem secsGem, IEnumerable<ISecsMessageHandler> messageHandlers)
    {
        _logger = logger;
        _secsConnection = secsConnection;
        _secsGem = secsGem;
        _messageHandlers = messageHandlers;

        _logger.LogInformation("SecsBackgroundService constructor called.");
        _logger.LogInformation($"SecsConnection: {_secsConnection.GetType().FullName}");
        _logger.LogInformation($"SecsGem: {_secsGem.GetType().FullName}");

        _secsConnection.ConnectionChanged += (sender, state) =>
        {
            _logger.LogInformation($"SECS connection state changed to: {state}");
        };
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            _logger.LogInformation("Starting SECS background service...");
            _secsConnection.Start(stoppingToken);
            _logger.LogInformation("SECS connection started.");

            await foreach (var primaryMessage in _secsGem.GetPrimaryMessageAsync(stoppingToken))
            {
                using var msg = primaryMessage.PrimaryMessage;
                _logger.LogInformation($"Received SECS message: {msg}");
                // 处理接收到的消息
                // await HandlePrimaryMessage(msg);

                // 分发消息到所有注册的消息处理器
                foreach (var handler in _messageHandlers)
                {
                    await handler.HandleMessageAsync(msg);
                }

                // 回复从消息
                using var secondaryMsg = CreateSecondaryMessage(msg);
                await primaryMessage.TryReplyAsync(secondaryMsg, stoppingToken);
            }
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("SECS background service is being cancelled.");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "An error occurred in the SECS background service.");
        }
    }

    private async Task HandlePrimaryMessage(SecsMessage primaryMessage)
    {
        // 这里可以根据具体业务逻辑处理主消息
        _logger.LogInformation($"Processing SECS message: {primaryMessage}");
    }

    private SecsMessage CreateSecondaryMessage(SecsMessage primaryMessage)
    {
        // 创建从消息,根据主消息的流和功能号创建
        return new SecsMessage(primaryMessage.S, (byte)(primaryMessage.F + 1)) { SecsItem = primaryMessage.SecsItem };
    }
}


SecsMessageHandler.cs


using Microsoft.Extensions.Logging;
using Secs4Net;

namespace SecsDemo.Application.Services;

public class SecsMessageHandler : ISecsMessageHandler
{
    private readonly ILogger<SecsMessageHandler> _logger;

    public SecsMessageHandler(ILogger<SecsMessageHandler> logger)
    {
        _logger = logger;
    }

    public async Task HandleMessageAsync(SecsMessage message)
    {
        _logger.LogInformation($"Handling SECS message: {message}");
        // 在这里添加具体的消息处理逻辑
        await Task.CompletedTask;
    }
}


ISecsMessageHandler.cs


using Secs4Net;

namespace SecsDemo.Application.Services;

public interface ISecsMessageHandler
{
    Task HandleMessageAsync(SecsMessage message);
}


posted on 2025-05-17 08:00  超级无敌美少男战士  阅读(72)  评论(0)    收藏  举报