Asp.net core ASP.NET 5中RegisterObject/QueueBackgroundWorkItem的等效项是什么

Asp.net core ASP.NET 5中RegisterObject/QueueBackgroundWorkItem的等效项是什么,asp.net-core,Asp.net Core,在“System.Web”ASP.NET中,可以通过RegisterObject/QueueBackgroundWorkItem注册后台工作,以参与IIS的关闭顺序(完成90秒的宽限期),但我很难在ASP.NET 5中找到确切的等效项 查看的源代码,我可以看到它通过iaapplicationlifecycle.ApplicationStopping和iaapplicationlifecycle.ApplicationStopping(在这两者之间,它处理服务器和PipelineInstance)

在“System.Web”ASP.NET中,可以通过
RegisterObject
/
QueueBackgroundWorkItem
注册后台工作,以参与IIS的关闭顺序(完成90秒的宽限期),但我很难在ASP.NET 5中找到确切的等效项

查看的源代码,我可以看到它通过
iaapplicationlifecycle.ApplicationStopping
iaapplicationlifecycle.ApplicationStopping
(在这两者之间,它处理服务器和
PipelineInstance
)发出信号,但是在旧的API中,似乎没有任何空间可以容纳90秒的宽限期,这就需要
RegisterObject

IIS集成层还没有开源(如果有的话),因此很难看到该实现是如何映射的

我是否缺少API?我是否应该通过
CancellationToken.Register()执行阻塞关机?这是“vNext的v1”中遗漏的内容吗


任何启示都将不胜感激。

我以基于武士刀的Hangfire实现为灵感,创作了以下内容。除了检查IIS Express终止时是否运行关闭代码外,它没有其他测试,但它可以作为概念证明

这里的设计显然不适用于“开火并忘记”任务,因为它们可能在关机之前被触发。但是,它确实适用于幂等队列处理器(假设已禁用空闲关机超时)


我仍然希望得到ASP.NET团队的反馈,但我刚刚注意到,Hangfire通过
CancellationToken.Register()
(尽管它的目标是检测关机的Katana等价物)选择阻塞关机(带超时)。
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...");
});