我正在构建一个 ASP.NET Core 应用程序,需要通过 SignalR 中心管理由客户端请求启动的长时间运行的任务(任务运行直到客户端关闭浏览器或检测到交互性)。据我所知,BackgroundService 通常作为单例运行,但我正在考虑使用其中的范围服务来进行任务实时硬件通信。这是一个简单的设置:
SignalR Hub:根据客户端连接启动任务。 单例后台服务:管理长时间运行的任务/作用域服务。 范围服务:在BackgroundService 中用于需要范围生命周期管理的操作,例如客户端与硬件和数据库的双工通信。 示例:
public class MyHub : Hub
{
public Task StartTask(string taskId)
{
BackgroundTaskManager.StartTask(taskId, Context.ConnectionId);
return Task.CompletedTask;
}
}
public class BackgroundTaskManager
{
private readonly IServiceScopeFactory _scopeFactory;
public BackgroundTaskManager(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public void StartTask(string taskId, string clientId)
{
using (var scope = _scopeFactory.CreateScope())
{
var service = scope.ServiceProvider.GetRequiredService<MyScopedService>();
service.PerformTask(taskId, clientId);
}
}
}
在单例BackgroundTaskManager 中使用作用域服务是处理此类任务的良好实践吗?这种方法有哪些潜在的陷阱?
是的,在托管服务中使用范围服务很好,并且在文档中进行了介绍 - 例如,在 ASP.NET Core 文档中使用托管服务进行后台任务的在后台任务中使用范围服务部分:
要在
内使用范围服务,请创建一个范围。默认情况下,不会为托管服务创建范围。BackgroundService
我认为,至少在某些情况下,“勾选”/“迭代”应该足够精细,特别是如果您使用 EF Core 之类的“标准”范围设置。 IE。
PerformTask
不应在整个应用程序时间内执行所有处理。