1

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.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • private static IServiceProvider _serviceProvider; – Ihdina Jul 22 '23 at 18:50
  • @Ihdina doesn't work. Same problem (( Because the problem is not in that part. The problem is in this code: `IServiceScope scope = _serviceProvider.CreateScope();` When applying for the second time, it says that it has already been disposed object. – Revan Zakaryali Jul 22 '23 at 18:56
  • 1
    What problem is this supposed to solve? My suspicion is that you don't actually need a timer. Btw: there are several different timers in dotnet, so it is always advisable to be specific about which one you are using. – Fildor Jul 22 '23 at 18:59
  • See if this helps: https://stackoverflow.com/questions/50200200/net-core-iservicescopefactory-createscope-vs-iserviceprovider-createscope-e – SoftwareDveloper Jul 22 '23 at 19:07
  • @SoftwareDveloper Thank you so much. I did it with IServiceFactory and it worked. When I tested it, didn't work because of a problem with AppDbContext service life time. – Revan Zakaryali Jul 22 '23 at 19:15
  • Remove `using` in front of `IServiceScope` and `AppDbContext` – Ihdina Jul 23 '23 at 01:01
  • What is the lifetime for ``EmailVerificationService``? how do you call the start method? – sa-es-ir Jul 23 '23 at 05:12

1 Answers1

1

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.

Alexander I.
  • 2,380
  • 3
  • 17
  • 42