在“System.Web”ASP.NET中,可以通过RegisterObject / QueueBackgroundWorkItem注册后台工作,以便参与IIS的关闭序列(完成90秒宽限期),但我很难找到完全等效的ASP.NET 5.
查看Microsoft.AspNet.Hosting.HostingEngine
的源代码,我可以看到它通过IApplicationLifecycle.ApplicationStopping和IApplicationLifecycle.ApplicationStopped发出信号(在它之间它处理服务器和PipelineInstance),但似乎没有任何空间需要90秒的宽限期旧API中的RegisterObject.
IIS集成层尚未开源(如果有的话),因此很难看出该实现如何映射事物.
我错过了一个API吗?我应该通过CancellationToken.Register()执行阻塞关闭吗?这是“vNext”中遗漏的东西吗?
任何启蒙都会受到高度赞赏.
解决方法
我使用基于Katana的Hangfire实现作为灵感来创建以下内容.除了检查IIS Express终止时关机代码运行之外,它没有任何测试,但它可以作为概念证明.
这里的设计显然不适用于“即发即忘”任务,因为它们可以在关机前触发.但它确实适用于幂等队列处理器(假设已禁用空闲关闭超时)
public static class BackgroundServiceExtensions { public static void UseBackgroundService( this IApplicationBuilder builder,Func<CancellationToken,Task> service) { var lifetime = (IApplicationLifetime)builder.ApplicationServices .GetService(typeof(IApplicationLifetime)); var stoppingToken = lifetime.ApplicationStopping; var stoppedToken = lifetime.ApplicationStopped; // This,in particular,would need to be properly thought out,// preferably including an execution context to minimise threadpool use // for async-heavy background services Task serviceTask = Task.Run(() => service(stoppingToken)); stoppedToken.Register(() => { try { // Block (with timeout) to allow graceful shutdown if (!serviceTask.Wait(TimeSpan.FromSeconds(30))) { // Log: Background service didn't gracefully shutdown. // It will be terminated with the host process } } catch(Exception) { // Ignored } }); } }
然后可以这样使用:
app.UseBackgroundService(async cancellationToken => { while (!cancellationToken.IsCancellationRequested) { System.Diagnostics.Debug.WriteLine("Tick..."); try { // Use cancellationToken for anything that is (logically) cancellable await Task.Delay(1000,cancellationToken); } catch(TaskCanceledException) { } } System.Diagnostics.Debug.WriteLine("Cancellation requested,shutting down..."); });