我希望在我的ASP.NET MVC 5应用程序中添加一些后台处理,更具体地说,使用HostingEnvironment.QueueBackgroundWorkItem执行一些长时间(5-10秒)的运行任务。现在,我遇到的问题是代码运行“带外”并且不再依赖于请求 - Autofac处理一些注入的依赖项。
以下是一些代码:
[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);
}
在上面的代码中,DependencyContainer是一个对象,它包含许多由Autofac(EF存储库和服务)注入的依赖项
private void ExecuteTask(CancellationToken ct, TaskList model)
{
model.TaskObject.Execute();
}
MissingCrossReferenceTask的execute方法内部(与ASP.NET MVC项目分开的程序集中:
public bool Execute()
{
long tableId = DependencyContainer.CrossReferenceService.GetCrossReferenceTable(TableName).Id;
string currentValue = DependencyContainer.CrossReferenceService.GetValue(FromValue, tableId);
...
}
第一行引发异常:ObjectDisposedExcetion {“ObjectContext实例已被释放,不能再用于需要连接的操作。”}
现在,我不知道Autofac是否能够找到解决此问题的最佳方法。是否有可能在ExecuteTask方法中直接重新引入引用?如果是这样 - 怎么样?
我非常感谢任何帮助。它已经让我疯了几天了......
谢谢, 尼克Goloborodko
答案 0 :(得分:0)
我想提交问题迫使我从一个稍微不同的角度来看问题。
我想我已经找到了解决这个问题的方法(换句话说 - 它现在可以按照我的意愿运行)。我仍然不确定这种方法在我的情况下是否是最好的,或者是否有任何看不见的问题 - 我非常感谢有关这个主题的任何评论!
我已通过以下方式解决了这个问题:
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();
}
}
(从此页面上发布的解决方案中采用:http://aboutcode.net/2010/11/01/start-background-tasks-from-mvc-actions-using-autofac.html)
希望将来可能会为其他人节省一些时间!