运行 应用程序启动期间的 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 函数一次。这就是我的解决方案。
每次应用程序启动时,我只需要 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 函数一次。这就是我的解决方案。