ASP.NET 5 中的 RegisterObject/QueueBackgroundWorkItem 等效于什么



在"System.Web"ASP.NET 中,可以通过RegisterObject/QueueBackgroundWorkItem注册后台工作,以便参与IIS的关闭序列(完成90秒宽限期),但我正在努力在第5 ASP.NET 中找到完全相同的等价物。

查看Microsoft.AspNet.Hosting.HostingEngine的源代码,我可以看到它通过 IApplicationLifecycle.ApplicationStoppingIApplicationLifecycle.ApplicationStopped 发出信号(它PipelineInstance之间释放服务器和 ),但似乎没有任何空间用于需要在旧 API 中RegisterObject的 90 秒宽限期。

IIS 集成层尚未开源(如果有的话),因此很难看出该实现如何映射事物。

我是否缺少 API?我应该通过CancellationToken.Register()执行阻塞关闭吗?这是"vNext 的 v1"遗漏的东西吗?

任何启发将不胜感激。

我使用基于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...");
});

相关内容

  • 没有找到相关文章

最新更新