Asp.Net - 使用 IHostedService 的计划任务

Asp.Net - Scheduled Task using IHostedService

我正在开发一个 ASP.NET Web 应用程序,该应用程序使用 C# 编写并托管在使用 IIS 10 作为 Web 服务器的 Azure 虚拟机中。我必须每天安排一次 运行 的后台任务。为此,我创建了以下 DailyTask class:

public class DailyTask : IHostedService {

    public Task StartAsync(CancellationToken cancellationToken) {
        Debug.WriteLine("start");
        Task.Run(TaskRoutine, cancellationToken);
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken) {
        Debug.WriteLine("stop");
        return null;
    }

    public Task TaskRoutine() {
        while (true) {
            try {
                /* ... */

                DateTime nextStop = DateTime.Now.AddDays(1);
                var timeToWait = nextStop - DateTime.Now;
                var millisToWait = timeToWait.TotalMilliseconds;
                Thread.Sleep((int)millisToWait);
            }

            catch (Exception e) {
                Debug.WriteLine(e);
            }
        }
    }
}

为了开始这项任务,我在 Startup class 中添加了以下语句:

public class Startup {
    public void ConfigureServices(IServiceCollection services) {
        /* ... */
        services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, HiddenUserCleaner>();
        /* ... */
    }
}

在我的测试服务器上部署后,我观察到该解决方案运行良好。但它可靠吗?生产中使用会不会有问题?

不安全。看看这里的指南:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-3.1&tabs=visual-studio

If the app shuts down unexpectedly (for example, the app's process fails), StopAsync might not be called. Therefore, any methods called or operations conducted in StopAsync might not occur.

实际情况并非如此,但它假设应用程序可以重新启动。偶尔重新启动的应用程序池也是如此。

总的来说,这并不能保证每天 运行。如果应用程序出于某种原因频繁重新启动,则可能是它从不 运行s。

像 hangfire 这样的库也是如此。

其他解决方案可以是 Web 作业,或者您可以通过使用某种持久性(例如存储上次执行时间的数据库)来检查它是否已在今天执行,并且 IHostingService 将每隔一段时间检查一次启动它是否应该执行后台作业并采取相应行动。