运行 应用程序启动期间的 IHostedService 函数,但只有一次

Run an IHostedService function during the Start of application but only once

每次应用程序启动时,我只需要 run a function once(该函数会检查我的数据库中的特定 Mongo collection 并插入我自己预定义的文档中).

IHostedService/BackgroundService 貌似能胜任。我只需要将服务注入我的 Startup.cs 文件。

但是,我想知道我是否可以优雅地完成这项任务,因为 IHostedService 确实是为了实现更多 cron job(一项需要 运行 在一个时间间隔内,比如每 30 分钟)。

谢谢。

编辑: 误区,应用启动后必须执行单个任务

有多种解决方法,但我会选择 IHostApplicationLifetime::ApplicationStarted。您可以创建一个扩展方法来注册您将在启动时执行的功能。

public static class HostExtensions
{
    public static void CheckMongoCollectionOnStarted(this IHost host)
    {
        var scope = host.Services.CreateScope();
        var lifetime = scope.ServiceProvider.GetService<IHostApplicationLifetime>();
        var loggerFactory = scope.ServiceProvider.GetService<ILoggerFactory>();
        var logger = loggerFactory!.CreateLogger("CheckMongoCollectionOnStarted");
        lifetime!.ApplicationStarted.Register(
            async () =>
            {
                try
                {
                    logger.LogInformation("CheckMongoCollectionOnStarted started");
                    //TODO: add your logic here
                    await Task.Delay(2000); //simulate working
                    logger.LogInformation("CheckMongoCollectionOnStarted completed");
                }
                catch (Exception ex)
                {
                    //shutdown if fail?
                    logger.LogCritical(ex, "An error has occurred while checking the Mongo collection. Shutting down the application...");
                    lifetime.StopApplication();
                }
                finally
                {
                    scope.Dispose();
                }
            }
        );
    }
}

然后从您的 Program class 呼叫分机:

public class Program
{
    public static async Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        host.CheckMongoCollectionOnStarted();
        await host.RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

我可以通过使用 IHostedService 实现我想要的。

protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            //logic
        }

在 Startup.cs 这就是我注册服务的方式。

AddSingleton<IHostedService, myService>

我 运行 我的应用程序,它调试到 AddSingleton 行并且只 运行 ExecuteAsync 函数一次。这就是我的解决方案。