0

I'm developing a Web Application for process a large amount of data and create a .csv file with those items.

So far, so good, but, it occored to me that it's not really fast this proccess, so I decide to make all those things in Task (Threading).

Like This:

_ = Task.Run(() => {
    try
    {
        LetsGoCrazy(model);
    }
    catch (Exception ex)
    {
        SaveLog(model, "Error dumbass", ex);
    }
});

My question is that, how can I update my database (Entity Framework Core) inside a Task Method?

Because, it shows me this Exception:

System.ObjectDisposedException: '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.

I believe that it must have another way to accomplish that without recreating the Entity Framework Context inside the Task.

Guilherme Golfetto
  • 510
  • 2
  • 5
  • 25
  • Yours is a _fire-and-forget_ `Task` that other parts of your code knows nothing about. You simply need to `await` the task returned from `Task.Run()`. Without seeing your code, simply placing it in a child task isn't necessarily going to make it run faster –  Feb 20 '20 at 00:47
  • 2
    @MichaelRandall haha I did like your analogy though :) –  Feb 20 '20 at 00:50
  • Weird analogy but makes sense bro haha. I can't make the user wait for the Task to finish. They'll receive a e-mail with the file afterall – Guilherme Golfetto Feb 20 '20 at 00:52
  • You might need some kind of message queueing service to handle `LetsGoCrazy` out of process. – ProgrammingLlama Feb 20 '20 at 00:55

1 Answers1

0

Yours is a fire-and-forget Task that other parts of your code knows nothing about. This means that the rest of the app continues on without waiting, releasing resources it thinks aren't being used or possibly exiting. This can happen quite easily in a console app if you aren't careful. For web you may find the controller goes out of scope and any resources along with it. By the looks of the error it appears to be the case.

You simply need to await the task returned from Task.Run().

try
{
   await Task.Run(() => LetsGoCrazy(model));
}
catch (SomeException ex)
{
   // ...
}

OP:

So far, so good, but, it occored to me that it's not really fast this proccess, so I decide to make all those things in Task (Threading).

Without seeing your code, simply placing it in a child task isn't necessarily going to make it run faster.

Dependency Injection Best Practices

You should avoid injecting I/O resources such as explicit database connections; WCF client proxies; or file streams into client code. This is because should the connection fault, the client (say a MVC Controller) has no way to re-create it.

Instead you should inject a provider object that client's invoke when a connection is required. Like everything else DI-related, object creation is still encapsulated by the DI system but it allows for dynamic object creation and recreation should a fault occur.

In your case if your LetsGoCrazy takes a long time (say > 5 mins) you might need to recreate the DB connection because of idle timeout.