Single. Net Core 3.1 Project с фоновой службой и MVC приложением - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь создать. Net Фоновую задачу / службу Core 3.1, которая также имеет. Net Интерфейс управления Core 3.1 MVC, все в одном проекте для легкого развертывания контейнером Docker. Мне нужна помощь с общей архитектурой кода, чтобы начать. Требования высокого уровня:

  • Одиночная. Net Базовая точка входа, не использующая пользовательский сценарий bash в качестве точки входа контейнера, которая запускает два отдельных проекта / двоичные файлы. Я видел несколько примеров bash сценариев, и я думаю, что он небрежный и делает связь из интерфейса управления с сервисом проблематичной c. Ваш ввод?

  • Веб-интерфейс MVC имеет полный контроль над фоновой задачей / службой, чтобы изменять ее параметры во время работы и / или перезапускать ее с изменениями конфигурации, установленными пользователем в системе управления. UI. Чем надежнее этот элемент управления, тем лучше, поскольку вся роль веб-интерфейса пользователя MVC заключается в управлении задачей / службой в режиме реального времени.

  • Фоновая задача / служба должна выполняться постоянно, независимо от того, состояния приложения MVC, используемого для управления. Другими словами, жизненный цикл фоновой задачи / службы должен быть гарантирован, даже если рабочие потоки для приложения MVC по какой-либо причине будут убиты или перезапущены.

Я очень доволен разработкой . Net Core MVC веб-приложений и API, и мне довольно удобно создавать фоновые сервисы в отдельных проектах. Тем не менее, я не уверен, как подходить к их объединению таким образом.

Я прилагаю свои первые усилия, приведенные ниже, в которых запускаются обе задачи, так что приложение MVC и фоновая служба запускаются, как и ожидалось, но я не могу управлять службой из приложения MVC из-за объема. Можете ли вы предложить какую-либо помощь о том, как я мог бы выполнить sh требования, перечисленные выше?

Program.cs (Работает для запуска обоих одновременно, но не позволяет приложению MVC контролировать сервис)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.DependencyInjection;

    namespace ServiceWithMvcManagement
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var hostManagement = CreateHostBuilderManagement(args).Build();
                var hostService = CreateHostBuilderService(args).Build();

                Task[] tasks = new Task[] {
                    hostManagement.RunAsync(),
                    hostService.RunAsync()
                };

                Task.WaitAll(tasks);
            }

            // MVC Management
            public static IHostBuilder CreateHostBuilderManagement(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });

            // Background Service
            public static IHostBuilder CreateHostBuilderService(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureServices((hostContext, services) =>
                    {
                        services.AddHostedService<Worker>();
                    });
        }
    }

Worker.cs (почти в наличии из шаблона фоновой службы)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ServiceWithMvcManagement
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

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

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    Debug.WriteLine("Worker running at: " + DateTimeOffset.Now.ToString());
                    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Exception: " + ex.Message);
                }
                finally
                {
                    await Task.Delay(1000, stoppingToken);
                }
            }
        }
    }
}

Startup.cs (полностью в наличии из MVC шаблона)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ServiceWithMvcManagement
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
...