c# - 如何确定在关机时调用 IHostedServices 的顺序?
问题描述
我正在维护一个集成包,它允许我的用户将我的库与 ASP.NET Core 集成。此包必须与从 2.1 开始的所有 ASP.NET Core 版本兼容。在应用程序关闭时,我的集成包必须能够执行异步清理,不幸的是不能依赖IAsyncDisposable
through Microsoft.Bcl.AsyncInterfaces
(见下文)。
因此,这似乎可行的唯一方法是注册一个IHostedService
实现。它的StopAsync
方法在关机时调用:
public sealed class ShutdownHostedService : IHostedService
{
public MyLibaryCleanupObject Obj;
public Task StartAsync(CancellationToken token) => Task.CompletedTask;
public Task StopAsync(CancellationToken token) => this.Obj.CleanupAsync();
}
services.AddSingleton<IHostedService>(new ShutdownHostedService { Obj = ... });
然而,应用程序开发人员当然可以添加他们自己的IHostedService
实现,这可能与我的库进行交互。这就是为什么IHostedService
最后调用我自己的实现很重要的原因。但问题就在这里。
随着 ASP.NET Core 2.1 的引入,应用程序开发人员可以在使用新Microsoft.Extensions.Hosting.Host
版本和(现已弃用)之间进行选择Microsoft.AspNetCore.WebHost
。With WebHost
, 在关闭时,IHostedService
实现按注册顺序调用,而 with Host
,IHostedService
实现按注册顺序相反的顺序调用。
这对我来说是个问题,因为我的托管服务应该最后调用。由于应用程序开发人员可能会在他们现有的 ASP.NET Core 应用程序中使用我的集成包,因此他们可能仍会使用WebHost
.,这就是支持该方案很重要的原因。
问题:确定 ASP.NET Core 应用程序在什么“模式”下运行的可靠方法是什么,以便我可以决定首先或最后添加我的托管服务?
或者,为了防止陷入 XY 问题陷阱,我愿意接受完全不同的解决方案来解决我实现“异步关闭”的问题。
注意事项IAsyncDisposable
:
想到的一种解决方案(正如 Ian 在评论中正确指出的那样)是将IAsyncDisposable
Singleton 注册添加到ServiceCollection
. 这将允许在关闭时进行异步清理。不幸的是,由于限制(在此处解释),我的集成包不可能依赖于Microsoft.Bcl.AsyncInterfaces
,因此也不可能依赖于IAsyncDisposable
. 这是一个不幸的情况,肯定会使事情复杂化。事实上,无法依赖IAsyncDisposable
的原因是我正在寻找实现异步关闭代码的替代方法的原因。
解决方案
我最终使用的解决方案与 MicrosoftMicrosoft.Extensions.Hosting.Internal.Host
班级选择的解决方案相同,并且不涉及使用IHostedService
实例。该类Host
包含以下Dispose
方法:
public void Dispose()
{
this.DisposeAsync().GetAwaiter().GetResult();
}
这可能会引起一些人的注意,并且可能被视为一种不好的做法,但不要忘记:
- 此代码保证在 ASP.NET Core 的上下文中运行,此代码不会导致死锁
- 此代码在关机时只运行一次,因此性能在这里不是问题。
这就是微软的Host
类可以采用这种方法的原因,这意味着我的库也可以采用这种安全方法。
推荐阅读
- java - “警报管理器设置重复”不是在 1 分钟内重复吗?
- flutter - Flutter:如何将前景添加到可关闭的小部件
- javascript - 表单输入数字 onchange
- c# - ASP.NET API 请求未成功完成
- java - 根据 JAX-RS 中的规范使用带有 @PathParam 的 PathSegment?
- flutter - Flutter BLoC:mapEventToState 的全局异常处理程序
- javascript - 如何一一执行 PHP 和 Javascript 代码?
- javascript - CryptoJS.HmacSHA256 与 Indy10 TIdHMACSHA256.HashValue
- java - 从 java -jar 运行 Spring Boot 应用程序时未提交事务
- reactjs - 如何在 React 中将多维数组作为道具传递?