Search code examples
c#asp.net.netservice

C# Timer - Cannot access a disposed object. Object name: 'IServiceProvider'


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.


Solution

  • 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.

    Additional information can be found there and there.