In" System.Web" ASP.NET,后台工作可以通过RegisterObject
/ QueueBackgroundWorkItem
注册,以便参与IIS的关闭顺序(完成90秒宽限期),但我很难找到ASP.NET 5中的完全等价物。
查看Microsoft.AspNet.Hosting.HostingEngine
的来源,我可以看到它通过IApplicationLifecycle.ApplicationStopping
和IApplicationLifecycle.ApplicationStopped
发出信号(在它之间配置服务器和PipelineInstance
),但是没有#39; t似乎是90秒宽限期内的任何空间,需要旧API中的RegisterObject
。
IIS集成层尚未开源(如果有的话),因此很难看出该实现如何映射事物。
我错过了API吗?我应该通过CancellationToken.Register()
执行阻止关闭吗?这是vnext""" v1的一部分。
任何启蒙都会受到高度赞赏。
答案 0 :(得分:6)
我使用基于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...");
});