Reputation: 3053
I'm looking to add some background processing to my ASP.NET MVC 5 application, more specifically executing some long-ish (5-10 seconds) running tasks with HostingEnvironment.QueueBackgroundWorkItem. Now, the problem that I'm having is that code is running "out of band" and is not tied to the request any more - Autofac disposes of some of the injected dependencies.
Here is some of the code:
[HttpPost, ActionName("Execute")]
public ActionResult ExecutePost(Guid taskguid, FormCollection values)
{
if (taskguid == default(Guid))
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var model = _taskListService.GetTaskByGuid(taskguid);
if (TryUpdateModel(model.TaskObject as MissingCrossReferenceTask))
{
model.TaskObject.DependencyContainer = _dependencyContainer;
model.TaskObject.TaskListId = model.Id;
HostingEnvironment.QueueBackgroundWorkItem(ct => ExecuteTask(ct, model));
return RedirectToAction("Index", "Dashboard");
}
return View(model);
}
In the code above DependencyContainer is an object that contains a number of dependencies that are injected by Autofac (EF Repositories and Services)
private void ExecuteTask(CancellationToken ct, TaskList model)
{
model.TaskObject.Execute();
}
Inside of that execute method of the MissingCrossReferenceTask (which is in a separate assembly from the ASP.NET MVC project:
public bool Execute()
{
long tableId = DependencyContainer.CrossReferenceService.GetCrossReferenceTable(TableName).Id;
string currentValue = DependencyContainer.CrossReferenceService.GetValue(FromValue, tableId);
...
}
The first line throws an exception: ObjectDisposedExcetion {"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}
Now, I don't know the Autofac well enough to figure out the best way around this. Is it somehow possible to re-inject the reference directly in ExecuteTask method? If so - how?
I would extremely appreciate any help of this. It has been driving me insane for a few days now...
Thanks, Nick Goloborodko
Upvotes: 2
Views: 1639
Reputation: 3053
I guess submitting the question has forced me to look at the problem from a slightly different angle.
I think I have found a way around this (in other words - it now works as I'd like it to). I'm still not sure if this approach is the best in my situation or if there are any unseen problems with it - I would much appreciate any comments around this topic!
I have solved the issue in the following way:
private void ExecuteTask(CancellationToken ct, TaskList model)
{
MvcApplication app = this.HttpContext.ApplicationInstance as MvcApplication;
using (var container = app.ContainerProvider.ApplicationContainer.BeginLifetimeScope(WebLifetime.Application))
{
model.TaskObject.DependencyContainer = container.Resolve<DependencyContainer>();
model.TaskObject.Execute();
}
}
(adopted from a solution posted on this page: http://aboutcode.net/2010/11/01/start-background-tasks-from-mvc-actions-using-autofac.html)
Hope this may save a bit of time to someone else in the future!
Upvotes: 1