英文:
BackgroundService and Service Lifetime .Net
问题
需要一些帮助来了解处理这个问题的“正确”方法。
我有一个应用程序,它启动一个始终运行并检查数据到达的后台服务。
当一些数据到达时,它将使用帮助服务将其写入本地数据库,唯一的要求是使用LiteDb。
因此,在正常情况下,这是一个简单的任务。
但是使用LiteDb创建了一个问题。
当我注册要完成写入数据库等其他工作的服务时,我需要传递LiteDb的一个实例。
唯一的问题是,使用这种方法LiteDb会一直保持打开状态,带有一个额外的文件(日志文件),这个文件看起来对我来说是一种事务或其他什么...阅读文档后,将所有内容“提交”到数据库文件的唯一方法就是释放LiteDb对象,因此使用这种方法是不可能的,因为服务与后台服务粘在一起,它对服务的生命周期不感兴趣...
所以我的主要问题是,我需要在服务中使用后处理对象。
那么如何处理这种情况?
在服务内部创建LiteDb,使用特定方法?
从构造函数中删除并通过方法注入,然后使用using包装服务调用?
还有其他选项吗?
谢谢
英文:
Need some help to see what's the "correct" approach to tackle this problem.
So I have this application that starts a background service that's always running and checking for arrival of data.
When some data arrives it'll be written to a local db, with the help with a helper service, the only requirement it's to use LiteDb.
So in normal conditions this was a simple task.
But using the LiteDb created a problem.
When I register the service that will do the work of writing to the db along other things, I need to pass an instance of LiteDb.
The only problem it's that using this approach the LiteDb stays open all the time with an extra file (log), file that looks to me that's kind of transactions or whatever... After reading the documentation the only way to "commit" everything to the db file it's disposing the LiteDb object, so using this approach it's not possible, because the service is glued to the background service, and it's indifferent to set the lifetime of the service...
So my main problem it's that I need to dispose the object in the service after it's been used.
So how to handle this kind of situation?
Newing the LiteDb inside the service, with a specific method for that?
Remove from the constructor and inject by method, and wrapping the service call with the using?
Any other option?
Thanks
答案1
得分: 1
你可能希望使用IServiceScopeFactory
或IScopedProcessingService
之一:
将IServiceScopeFactory
作为构造函数参数注入到您的后台服务中,您可以使用它生成范围以解析服务并执行操作,然后可以在周期之间进行处理。IScopedProcessingService
也可以类似地工作。
public class MyBackgroundService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
public MyBackgroundService(IServiceScopeFactory scopeFactory, ILogger<MyBackgroundService> logger)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _scopeFactory.CreateScope())
{
var dependencyOne = scope.ServiceProvider.GetRequiredService<IFirstDependency>();
var dependencyTwo = scope.ServiceProvider.GetRequiredService<ISecondDependency>();
// do work
}
await Task.Delay(5000, stoppingToken);
}
}
}
英文:
You probably want to use either IServiceScopeFactory
or IScopedProcessingService
:
Injecting IServiceScopeFactory
as a constructor parameter into your background service, you can use it to generate scopes to resolve services and perform actions which can then be disposed of in between cycles. IScopedProcessingService
works similarly.
public class MyBackgroundService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger _logger;
public MyBackgroundService(IServiceScopeFactory scopeFactory, ILogger<MyBackgroundService> logger)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _scopeFactory.CreateScope())
{
var dependencyOne = scope.ServiceProvider.GetRequiredService<IFirstDependency>();
var dependencyTwo = scope.ServiceProvider.GetRequiredService<ISecondDependency>();
// do work
}
await Task.Delay(5000, stoppingToken);
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论