.net-core - 重写 IHostedService 以在所有任务完成后停止
问题描述
我有一个应用程序,它通常应该是一个简单的控制台应用程序,被编程为 Windows 任务调度程序不时调用的计划任务。
该程序应该在两个数据库上启动一些更新,每个数据库一个服务。说ContosoDatabase
应该由ContosoService
.
最后,它被编写为一个 .NET Core 应用程序,使用s 作为服务的基础,这可能不是最佳选择,如下所示:IHostedService
public class ContosoService : IHostedService {
private readonly ILogger<ContosoService> _log;
private readonly IContosoRepository _repository;
private Task executingTask;
public ContosoService(
ILogger<ContosoService> log,
IContosoRepository repository,
string mode) {
_log = log;
_repository = repository;
}
public Task StartAsync(CancellationToken cancellationToken) {
_log.LogInformation(">>> {serviceName} started <<<", nameof(ContosoService));
executingTask = ExcecuteAsync(cancellationToken);
// If the task is completed then return it,
// this should bubble cancellation and failure to the caller
if (executingTask.IsCompleted)
return executingTask;
// Otherwise it's running
// >> don't want it to run!
// >> it should end after all task finished!
return Task.CompletedTask;
}
private async Task<bool> ExcecuteAsync(CancellationToken cancellationToken) {
var myUsers = _repository.GetMyUsers();
if (myUsers == null || myUsers.Count() == 0) {
_log.LogWarning("{serviceName} has any entry to process, will stop", this.GetType().Name);
return false;
}
else {
// on mets à jour la liste des employés Agresso obtenue
await _repository.UpdateUsersAsync(myUsers);
}
_log.LogInformation(">>> {serviceName} finished its tasks <<<", nameof(ContosoService));
return true;
}
public Task StopAsync(CancellationToken cancellationToken) {
_log.LogInformation(">>> {serviceName} stopped <<<", nameof(ContosoService));
return Task.CompletedTask;
}
}
我像这样从 main 调用它:
public static void Main(string[] args)
{
try {
CreateHostBuilder(args).Build().Run();
}
catch (Exception ex) {
Log.Fatal(ex, ">>> the application could not start <<<");
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host
.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) => {
var config = hostContext.Configuration;
if (args.Contains("Alonso")) {
services
.AddHostedService(provider =>
new AlonsoService(
provider.GetService<ILogger<AlonsoService>>(),
provider.GetService<IAlonsoRepository>()));
}
// if there also Cedig in the list, they can be run in parallel
if (args.Contains("Contoso")) {
services
.AddHostedService(provider =>
new ContosoService(
provider.GetService<ILogger<ContosoService>>(),
provider.GetService<IContosoRepository>()));
}
});
现在,问题肯定是,一旦所有更新完成,应用程序就不会停止。
有没有办法快速重写应用程序以使其在第二个服务完成其任务后停止?
我试图Environment.Exit(0);
把
public static void Main(string[] args) {
try {
CreateHostBuilder(filteredArgs.ToArray()).Build().Run();
}
catch (Exception ex) {
//Log....
}
Environment.Exit(0); // here
}
但这似乎没有帮助:所有任务完成后应用程序仍在运行。
解决方案
HostedServices 是后台服务。反之亦然:它们可以对应用程序的启动和停止事件做出反应,以便它们可以优雅地结束。它们并不意味着在完成后停止您的主应用程序,它们可能与应用程序一样长。
我想说简单的任务会更好地为您服务并等待所有任务。或者当你的后台作业完成它的工作并在 main 中处理它们时发送一些事件。
无论您选择什么触发器,您都可以通过注入 IHostApplicationLifetime 并在其上调用 StopApplication() 方法来停止 .net 应用程序。在早期版本中,它只是 IApplicationLifetime。
推荐阅读
- php - 如何使用 php 将数据写入格式化和样式化的 xls 文件(更新数据)
- ansible - 如何让一个分子平台无法通过测试?
- python - 配置 Lighttpd 以使用 fastcgi 运行 python 脚本
- python - XGboost 算法:传递一个不是回归量的变量
- java - Gradle 编译失败“找不到 com.github.everit-org.json-schema:org.everit.json.schema:1.11.1。” 在 Hyperledger Fabric 中
- java - pom.xml中添加spring security时登录不成功
- mysql - 使用拆分“读取”和“写入”数据库连接时 Laravel 中的竞争条件
- angular - 如何安装特定版本的 Angular Material?
- python - 插入多行,其中插入语句的列的所有值都相同,除了一列
- node.js - How to remove _id from aggregate $match & $group query