实现IStartupTask,在DI中注册StartupTaskRunner和YourStartupTask:
services
.AddStartupTasksRunner()
.AddStartupTask<YourStartupTask>();
这里的代码基于Andrew's Lock 帖子:
public interface IAsyncStartupTask
{
Task OnStartupAsync(CancellationToken cancellationToken);
}
internal class StartupTasksRunner : IHostedService
{
private readonly IEnumerable<IAsyncStartupTask> _startupTasks;
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly SemaphoreSlim _semaphore;
public StartupTasksRunner(IEnumerable<IAsyncStartupTask> startupTasks, IHostApplicationLifetime applicationLifetime)
{
_startupTasks = startupTasks;
_applicationLifetime = applicationLifetime;
_semaphore = new SemaphoreSlim(0);
applicationLifetime.ApplicationStarted.Register(() => _semaphore.Release());
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// wait for ApplicationStarted event to execute when app is listening to web requests
// await _semaphore.WaitAsync(cancellationToken);
foreach (var task in _startupTasks)
{
try
{
await task.OnStartupAsync(cancellationToken).ConfigureAwait(false);
}
catch
{
// stop the application if failing startup task if fatal
//_applicationLifetime.StopApplication();
throw;
}
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddStartupTasksRunner(this IServiceCollection services)
{
return services.AddHostedService<StartupTasksRunner>();
}
public static IServiceCollection AddStartupTask<TStartupTask>(this IServiceCollection services)
where TStartupTask : class, IAsyncStartupTask
{
return services.AddSingleton<IAsyncStartupTask, TStartupTask>();
}
}
备注
应用startup order是:
- 开始
HostedService的
- 启动 Kesterl 服务器
- 触发
ApplicationStarted事件
如果您想在HostedServices 开始之前运行您的启动任务,您需要确保StartupTasksRunner 在任何其他HostedService 之前注册(它们按照注册顺序启动)。 p>
如果您希望在所有HostedServices 启动后但在应用程序开始接收网络请求之前运行您的启动任务,请确保您在任何一个之后注册StartupTasksRunner其他HostedService。
如果您想在 Kestrel 服务器启动后运行您的启动任务,请取消注释 // await _semaphore.WaitAsync(cancellationToken); 行。请注意,它可能与 Web 请求处理同时运行。
还要注意IHostedService.StartAsync 方法抛出的异常将被框架swallowed。因此,如果您的应用程序需要成功执行启动任务,请取消注释 // _applicationLifetime.StopApplication();