1

I have a class with an scoped _repository and one async method MethodAsync(....) I call the method without await (fire and forget). I want to use the injected dependency after the await (in the catch), but the request is over at that time, and I got an error saying: Cannot access a disposed object.

I think getting that error is the expected behavior, but How can I use injected dependencies in this way? I could inject the ServiceProvider and ask for dependencies, but injecting the ServiceProvider is a bad practice. How can I solve this without injecting the ServiceProvider?

I call the method like this:

example.MethodAsync(....);//without await

This is the class

public class Example
{
    private readonly Repository _repository;

    public Example(Repository repository)
    {
        _repository = repository;
    }

    public async Task MethodAsync(....)
    {
        try
        {
            await DoSomething();
        }
        catch (Exception e)
        {
            _repository.Example.Remove(....);
        }
    }
}
satellite satellite
  • 893
  • 2
  • 10
  • 27
  • What object is the error thrown in that is disposed? – Jawad Jul 13 '20 at 02:46
  • 1
    You can resolve it by `await`ing your call. Your service is scoped, if you fire-forget the call, your DI will dispose it because the request is considered done. – JohanP Jul 13 '20 at 02:49
  • I think in your (try) statement you use (using) statement so dispose object automate please show your repository class – Akbar Asghari Jul 13 '20 at 03:19
  • @Jawad The error is on _repository object. The full error is: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'DbContext'. – satellite satellite Jul 13 '20 at 03:42
  • @JohanP you're rigth, but, I want to NOT await. – satellite satellite Jul 13 '20 at 03:43
  • @AkbarAsghari Im not using the 'using block'. The error is cause the request is over and the _repository is injected as scoped. My Repository class is a DbContext, but it could be any dependency – satellite satellite Jul 13 '20 at 03:43
  • 1
    Probably you should inject the factory that will create the repository. Accordingly, the Dispose should be inside catch. – Alexander Petrov Jul 13 '20 at 03:46
  • @AlexanderPetrov Interesting, inject a Factory for the Repository. Thanks – satellite satellite Jul 13 '20 at 03:51
  • please use Interface for inject I don't see any interface for your repository – Akbar Asghari Jul 13 '20 at 03:53
  • 1
    Related: https://stackoverflow.com/a/45164677/264697 – Steven Jul 13 '20 at 08:10
  • 1
    Related: https://stackoverflow.com/a/26698472/264697 – Steven Jul 13 '20 at 08:11

1 Answers1

1

You are able to both execute it in a fire and forget manner while using the full DI capabilities by using a job scheduler.

By doing so, you are furthermore able to keep track of the state of the executed job. Furthermore configuring retry-on-failure would be feasible.

I am using Hangfire for this job:

BackgroundJob.Enqueue<Example>(service => service.MethodAsync());