Как использовать уже работающую Net Core WorkerService в веб-приложении? - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь получить доступ к журналу, созданному рабочей службой в моем веб-приложении. Я сделал тестовое решение: enter image description here

У меня есть интерфейс ILogGenerator для создания журнала и рабочий, который его реализует:

public interface ILogGenerator
{
    event EventHandler<string> LogGenerated;
}

public class Worker : BackgroundService, ILogGenerator
{
    private readonly ILogger<Worker> _logger;

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

    public event EventHandler<string> LogGenerated;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var log = $"Worker running at: {DateTimeOffset.Now} {new Guid()}";

            LogGenerated?.Invoke(this, log);

            _logger.LogInformation(log);
            await Task.Delay(10000, stoppingToken);
        }
    }
}

From Startup in мое веб-приложение, я добавляю его как размещенную службу:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();

        services.AddHostedService<Worker>();

        services.AddTransient<WorkerConsumer>();
    }

У меня есть workerconsumer, которому я хочу распечатать журнал в консоли:

public class WorkerConsumer
{
    public WorkerConsumer(ILogGenerator worker)
    {
        worker.LogGenerated += Worker_LogGenerated;
    }

    private void Worker_LogGenerated(object sender, string e)
    {
        Debug.WriteLine(e);
    }
}

Я добавляю оба проекты для запуска: enter image description here

Когда я запускаю приложение, я получаю эту ошибку. enter image description here

Если я не вызываю рабочего потребителя, он работает, но я получаю два WorkerService1.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();

        services.AddHostedService<Worker>();

        //services.AddSingleton<WorkerConsumer>();
    }

Если я не добавляю рабочая служба для запуска, и я добавляю рабочего-потребителя на страницу индекса, она работает, но рабочая служба больше не работает как отдельное консольное приложение.

Обновление 1: My Program.cs из WorkerService выглядит так:

namespace WorkerService1
{
    public class Program
    {
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                    // services.AddTransient<ILogGenerator>(l => l.GetRequiredService<Worker>());
                });

        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    }
}

Startup.cs ConfigureServices моего веб-приложения выглядит так:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();

            // services.AddHostedService<Worker>();
            services.AddTransient<ILogGenerator>(l => l.GetRequiredService<Worker>());

            services.AddTransient<WorkerConsumer>();
        }

Сначала я запускаю рабочую службу, затем веб-приложение и получаю: enter image description here

Насколько я понимаю, рабочая служба регистрируется на хосте, и веб-приложение должно иметь возможность извлекать эту рабочую службу с хоста, это правильно?

Ответы [ 2 ]

0 голосов
/ 26 мая 2020

Для работы вашего кода необходим экземпляр ILogGenerator, предоставленный издателем и наблюдателями. Вместо этого я сделаю что-то подобное:

LogGenerator

public class LogGenerator : ILogGenerator
{
     public event EventHandler<string> LogGenerated;
     public void OnLogGenerated(string log)
     {
        LogGenerated?.Invoke(this, log);
     }
}

Worker

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly LogGenerator _generator;

    public Worker(ILogger<Worker> logger, LogGenerator generator)
    {
        _logger = logger;
       _generator = generator;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var log = $"Worker running at: {DateTimeOffset.Now} {new Guid()}";

            _generator.OnLogGenerated(log);

            _logger.LogInformation(log);
            await Task.Delay(10000, stoppingToken);
        }
    }
}

Вам нужно сообщить контейнеру DI, что делать при запросе ILogGenerator:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();

            services.AddSingleton<LogGenerator>();
            services.AddTranscient<ILogGenerator>(p => p.GetRequiredService<LogGenerator>());

            services.AddHostedService<Worker>();
        }
0 голосов
/ 26 мая 2020

Согласно вашему сообщению об ошибке, у вас проблема с внедрением зависимостей.

Вероятно, это происходит из-за того, что вы забыли зарегистрировать интерфейс ILogGenerator с его соответствующей реализацией в IServiceCollection.

С уважением,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...