.NET Core中HostingEnvironment.QueueBackgroundWorkItem的替代解决方案 [英] Alternative solution to HostingEnvironment.QueueBackgroundWorkItem in .NET Core

查看:273
本文介绍了.NET Core中HostingEnvironment.QueueBackgroundWorkItem的替代解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在与.NET Core Web Api合作,正在寻找一种轻量级的解决方案以将强度可变的请求记录到数据库中,但不希望客户端等待保存过程。
不幸的是没有在 dnx Task.Run(中实现的 HostingEnvironment.QueueBackgroundWorkItem(..) 。)是不安全的。

是否有任何优雅的解决方案?

We are working with .NET Core Web Api, and looking for a lightweight solution to log requests with variable intensity into database, but don't want client's to wait for the saving process.
Unfortunately there's no HostingEnvironment.QueueBackgroundWorkItem(..) implemented in dnx, and Task.Run(..) is not safe.
Is there any elegant solution?

推荐答案

QueueBackgroundWorkItem 不见了,但是我们有了 IApplicationLifetime 而不是 IRegisteredObject ,由前一个使用。

QueueBackgroundWorkItem is gone, but we've got IApplicationLifetime instead of IRegisteredObject, which is being used by the former one. And it looks quite promising for such scenarios, I think.

这个主意(我仍然不太确定,如果这是一个很糟糕的主意,请当心! )是注册一个单例,它会生成观察新任务。在该单例中,我们还可以注册一个已停止的事件,以便适当地等待仍在运行的任务。

The idea (and I'm still not quite sure, if it's a pretty bad one; thus, beware!) is to register a singleton, which spawns and observes new tasks. Within that singleton we can furthermore register a "stopped event" in order to proper await still running tasks.

此概念可用于诸如日志记录,邮件发送等。事情应该花很长时间,但是会为当前请求产生不必要的延迟。

This "concept" could be used for short running stuff like logging, mail sending, and the like. Things, that should not take much time, but would produce unnecessary delays for the current request.

public class BackgroundPool
{
    protected ILogger<BackgroundPool> Logger { get; }

    public BackgroundPool(ILogger<BackgroundPool> logger, IApplicationLifetime lifetime)
    {
        if (logger == null)
            throw new ArgumentNullException(nameof(logger));
        if (lifetime == null)
            throw new ArgumentNullException(nameof(lifetime));

        lifetime.ApplicationStopped.Register(() =>
        {
            lock (currentTasksLock)
            {
                Task.WaitAll(currentTasks.ToArray());
            }

            logger.LogInformation(BackgroundEvents.Close, "Background pool closed.");
        });

        Logger = logger;
    }

    private readonly object currentTasksLock = new object();

    private readonly List<Task> currentTasks = new List<Task>();

    public void SendStuff(Stuff whatever)
    {
        var task = Task.Run(async () =>
        {
            Logger.LogInformation(BackgroundEvents.Send, "Sending stuff...");

            try
            {
                // do THE stuff

                Logger.LogInformation(BackgroundEvents.SendDone, "Send stuff returns.");
            }
            catch (Exception ex)
            {
                Logger.LogError(BackgroundEvents.SendFail, ex, "Send stuff failed.");
            }
        });

        lock (currentTasksLock)
        {
            currentTasks.Add(task);

            currentTasks.RemoveAll(t => t.IsCompleted);
        }
    }
}

这样的 BackgroundPool 应该注册为单例,并且可以通过DI由任何其他组件使用。我目前正在使用它来发送邮件,并且工作正常(也已在应用关闭时测试了邮件的发送)。

Such a BackgroundPool should be registered as a singleton and can be used by any other component via DI. I'm currently using it for sending mails and it works fine (tested mail sending during app shutdown too).

注意:访问诸如当前的 HttpContext 在后台任务中不起作用。 旧解决方案使用 UnsafeQueueUserWorkItem 禁止这样做。

Note: accessing stuff like the current HttpContext within the background task should not work. The old solution uses UnsafeQueueUserWorkItem to prohibit that anyway.

您怎么看?

更新:

有了ASP.NET Core 2.0,后台任务有了新的东西,而ASP.NET Core 2.1更好了:在.NET中实现后台任务具有IHostedService和BackgroundService类的Core 2.x Web应用程序或微服务

With ASP.NET Core 2.0 there's new stuff for background tasks, which get's better with ASP.NET Core 2.1: Implementing background tasks in .NET Core 2.x webapps or microservices with IHostedService and the BackgroundService class

这篇关于.NET Core中HostingEnvironment.QueueBackgroundWorkItem的替代解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆