1

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

IHostedService/BackgroundService似乎能够胜任这项工作。我只需要将服务注入到我的 Startup.cs 文件中。

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

谢谢你。

4

2 回答 2

1

编辑:误解,必须在应用程序启动后执行单个任务。

有多种方法可以解决它,但我会选择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然后从您的班级调用扩展程序:

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>());
}
于 2021-08-11T03:47:46.343 回答
1

我能够通过使用 IHostedService 来实现我想要的。

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

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

AddSingleton<IHostedService, myService>

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

于 2021-08-12T03:18:22.393 回答