如何在没有http请求的MVC Core应用程序中启动HostedService

ado*_*lot 7 c# asp.net-core asp.net-core-hosted-services

在我的MVC .NET核心2.2应用程序中,有HostedService进行后台工作.

它是在Startap类的ConfigureServices方法中注册的

services.AddHostedService<Engines.KontolerTimer>();
Run Code Online (Sandbox Code Playgroud)

由于这是独立于用户请求的后台服务,因此我想在应用启动时立即启动后台服务.现在是我的HostedService在第一次用户请求后盯着的情况.

在MVC Core应用程序启动时启动HostedService的正确方法是什么

我的服务看起来像这个https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2

internal class TimedHostedService : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private Timer _timer;

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

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("Timed Background Service is working.");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来我有问题盯着应用程序.

我的porgram cs看起来像

public class Program
    {
        public static void Main(string[] args)
        {
           CreateWebHostBuilder(args).Build().Run();


        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .UseSerilog((ctx, config) => { config.ReadFrom.Configuration(ctx.Configuration); })
            .UseStartup<Startup>();
    }
Run Code Online (Sandbox Code Playgroud)

在第一次用户请求之前我没有遇到任何断点.我错过了什么,这是由VS2017创建的默认.Net核心应用程序

这是我的starup.cs

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

        public IConfiguration Configuration { get; }
        private Models.Configuration.SerialPortConfiguration serialPortConfiguration;

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            services.AddIdentity<ApplicationUser, ApplicationRole>(options => options.Stores.MaxLengthForKeys = 128)
                .AddDefaultUI(UIFramework.Bootstrap4)
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();

            services.AddDbContext<Data.Parking.parkingContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));


         services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddHostedService<Engines.KontolerTimer>();}
Run Code Online (Sandbox Code Playgroud)

Kir*_*kin 14

当您使用 Visual Studio 运行它时,您可能使用的是 IIS Express,它不会在发出第一个请求之前运行您的 ASP.NET Core 项目(这就是 IIS 默认的工作方式)。这适用于使用 ASP.NET Core 2.2 新的 InProcess 托管模型,我希望您必须使用它才能看到此问题。有关更多信息,请参阅此GitHub 问题

您可以通过从用于托管 ASP.NET Core 应用程序的 .csproj 文件中删除 AspNetCoreHostingModel XML 元素来证明这一理论(这会将其切换回 OutOfProcess 模式)。看起来VS2017的项目属性对话框中的“调试”下有一个“托管模型”选项,如果您不想直接编辑.csproj,可以将其更改为“进程外”。

例如,如果您希望托管模型仅用于生产站点的进程外,您可以使用 Web.config 转换。如果您希望它在开发和生产期间都处于进程外状态,只需更改我上面提到的属性就足够了,因为它会自动转换为 Web.config 属性。如果您更喜欢使用进程内模型,那么在 IIS 应用程序中启用预加载是一个不错的选择(在此处描述)。