In the code I posted, it works in the first period. When entering the second period, it gives this error:
Unhandled exception.
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
I have checked everything. What do you think could be the reason?
public class EmailVerificationService
{
private Timer? _timer;
private string? _email;
private IServiceProvider _serviceProvider;
public EmailVerificationService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Start(string email)
{
_email = email;
_timer = new Timer(CheckVerificationExpiration, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
}
private async void CheckVerificationExpiration(object state)
{
var now = DateTime.UtcNow;
using IServiceScope scope = _serviceProvider.CreateScope();
using AppDbContext dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
User? user = await dbContext.Users
.Where(u => u.Email == _email && now >= u.ConfirmCodeExpires)
.FirstOrDefaultAsync();
if (user != null)
{
dbContext.Users.Remove(user);
dbContext.SaveChanges();
}
}
}
I checked everything. I changed service life time. I then tried creating the IServiceFactory
in the Start
method. It just didn't work to use the same service for all of them.
I suggest to use IServiceScopeFactory
instead of IServiceProvider
in the constructor.
The lifetime of IServiceScopeFactory
is Singleton
. It means you can have access to this interface everywhere.
The lifetime of IServiceProvider
is Scoped
. So it seems when your EmailVerificationService
will be out of scope then IServiceProvider
will be disposed and you will see the error.