.NET Core中HostingEnvironment.QueueBackgroundWorkItem的替代解决方案

编程入门 行业动态 更新时间:2024-10-22 02:39:53
本文介绍了.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的替代解决方案

本文发布于:2023-11-14 19:28:55,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:解决方案   Core   NET   QueueBackgroundWorkItem   HostingEnvironment

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!