如何在 asp net core 3.1 中保持托管服务的活动状态?

5 c# asp.net-core asp.net-core-webapi asp.net-core-3.0

你好吗?。

我在 net core 3.1 中有一个 web api,这又包含一个服务,每 X 分钟必须运行一次以执行数据迁移(我只是在测试它),但我有两个问题。

  1. 要运行该服务,我必须首先运行我的 api 的一些 url。问题是:如何让这个服务自动启动,而不需要运行任何api?
  2. 当我停止使用 apis 几分钟时,服务停止工作。问题是:我怎样才能让服务“永远”保持活力?

我必须强调,我的 web api 托管在虚拟主机中,我无法访问 IIS 的所有功能

这是我的代码,在此先感谢您的帮助。

MySuperService.cs

 public class MySuperService : IHostedService, IDisposable
{
    private bool _stopping;
    private Task _backgroundTask;
    private static readonly log4net.ILog log =log4net.LogManager.GetLogger(typeof(MySuperService));
    public Task StartAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("MySuperService is starting.");
        log.Info("MySuperService is starting.");
        _backgroundTask = BackgroundTask();
        return Task.CompletedTask;
    }

    private async Task BackgroundTask()
    {
        int contador = 1;
        while (!_stopping)
        {
            Console.WriteLine("MySuperService is working--> " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            log.Info("MySuperService is working--> " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            await Task.Delay(TimeSpan.FromMinutes(3));
            contador++;
        }

        Console.WriteLine("MySuperService background task is stopping.");
        log.Info("MySuperService background task is stopping.");
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("MySuperService is stopping.");
        log.Info("MySuperService is stopping.");
        _stopping = true;
        if (_backgroundTask != null)
        {
            // TODO: cancellation
            await BackgroundTask();
            //await _backgroundTask;
        }
    }

    public void Dispose()
    {
        Console.WriteLine("MySuperService is disposing.");
        log.Info("MySuperService is disposing.");
    }
}
Run Code Online (Sandbox Code Playgroud)

程序.cs

public class Program
{
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));
    public static void Main(string[] args)
    {
        ...
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            }).ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<MySuperService>();
            });
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*man 5

继承而BackgroundService不是实现IHostedService。这将为您处理启动、运行和停止服务的机制。

然而,您面临的问题是 IIS 在第一次请求服务之前不会启动您的 C# 进程。然后,如果没有请求,默认应用程序池设置将再次将其关闭。我建议设置某种计划任务来定期请求 URL 并监视服务是否正在运行。如果它停止了,您会希望收到通知,对吧?


Asp*_*per 0

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.0&tabs=visual-studio

如果您从BackgroundService类继承无限作业服务并在循环内实现您的逻辑以及所需的

await Task.Delay(TimeSpan.FromMinutes(x miutes))
Run Code Online (Sandbox Code Playgroud)

该作业将在应用程序启动后立即运行,无需任何 API 调用,并在应用程序停止时停止。

 public class MyService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            Console.WriteLine("test");

            //await run job

            await Task.Delay(TimeSpan.FromSeconds(1));
        }
    }

    public override async Task StartAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("start");

        await ExecuteAsync(cancellationToken);
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("stop");

        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么要继承“BackgroundService”,然后重写实际使其工作的两个方法? (5认同)
  • 这是错误的做法。由于 IGenericHost 设计(托管服务在服务器 Kestrel 之前启动),StartAsync 必须返回。StartAsync 必须尽快返回(返回 Task.CompletedTask)。您可以通过注入 IHostApplicationLifetime 来验证这一点,您将看到 OnStarted 在您终止应用程序后被触发。 (3认同)