Reputation: 371
I have created a Background Service in my Server Solution
public class PurgeService : IHostedService, IDisposable
{
private readonly IServiceProvider _provider;
private Timer timer;
public PurgeService(IServiceProvider serviceProvider)
{
using (IServiceScope scope = serviceProvider.CreateScope())
{
_provider = scope.ServiceProvider;
}
}
public void Dispose()
{
timer?.Dispose();
}
public Task Purge(IServiceProvider serviceProvider)
{
var dbcontext = serviceProvider.GetRequiredService<ApplicationDBContext>();
var setting = dbcontext.AppSet.First();
double deletetime = setting.PurgeTimer *(1);
DateTime deletedate = DateTime.Now.AddHours(deletetime);
string deleteSQL = $"DELETE FROM Notifications WHERE CreatedDate > {deletedate}"
}
public Task StartAsync(CancellationToken cancellationToken)
{
timer = new Timer(x => Purge(_provider), null, TimeSpan.Zero, TimeSpan.FromSeconds(10));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
And added it to the Startup.cs
services.AddHostedService<PurgeService>();
My goal is to have a background service that checks every 10 seconds if there are notifications older than allowed and deletes them.
But when I run the app an error occurs
"System.ObjectDisposedException: "Cannot access a disposed object."
How can I implement this correctly?
Upvotes: 2
Views: 767
Reputation: 371
The problem was that the database table was empty, but the null exception threw a completely different exception.
Upvotes: -1
Reputation: 21699
Your constructor seems to be establishing a scope, and immediately disposing the scope. Your provider is tied to that scope so gets nuked immediately in the constructor when Dispose() is called on the scope due to using
.
Background services are usually singletons with a lifetime equivalent to the lifetime of the the application. It seems to me you should register your service as a singleton outside of the service class itself. Something like
public class PurgeService : IHostedService
{
// no weird constructor taking in IServiceProvider
}
Also, using an IoC inside of a class is a bit of an antipattern. Inject a DB context factory instead of trying to resolve through a container inside your class.
Upvotes: 2