Я пытаюсь создать. 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?}");
});
}
}
}