1

我没有为我的目的找到类似的问题/答案。

在我的控制器(MVC 4/EF 5 应用程序)的一些操作中,我有更新数据库的功能,但这些功能不影响用户输出(选择后更新信息的功能)。我想在异步线程中发送这些函数(这将在用户获得渲染页面后完成)。我不想等待线程完成并渲染页面。在这种情况下,数据库上下文呢?我的上下文生命周期是“每个请求”,它在 Application_EndRequest 中删除:

protected virtual void Application_EndRequest()
{
    var entityContext = HttpContext.Current.Items["_Context"] as DbContext;
    if (entityContext != null)
        entityContext.Dispose();
}

我在线程中使用自己的上下文(使用块进行正确处理)。

using (DbContext db = new DbContext())
{
    ....
}

但是,如果我想在线程中将实体附加到 DbContext,我会在几种情况下收到错误消息“ObjectStateManager 中已存在具有相同键的对象”。这很奇怪,因为我使用带有 AsNoTracking() 选项的加载,并且实体状态在调用新线程之前在主上下文中“分离”。在其他情况下,当我在线程中再次尝试来自数据库的请求实体并对其进行修改(而不是附加)时,我多次出现错误“对象处于分离状态” Context 的两个实例是否使用一个 ObjectStateManager?并且错误的出现取决于主线程上下文处理的时间。我的意思是在处理主上下文之前或之后我在线程中使用上下文......

在这种情况下,如何使用具有自己的上下文的异步线程?谢谢。

4

2 回答 2

2

你在这里有几个问题:

1)如果您使用属于一个上下文的对象或导航属性并尝试在另一个上下文中使用它们,您将得到您所看到的错误。

2)一旦您的请求完成,IIS 就可以自由地回收AppDomain.当这种情况在生产中发生时,您的工作线程将因极端偏见而中止。这意味着您根本不能依赖工作线程做任何事情。

如果你想推迟一些昂贵的工作,你应该将工作传递给在另一个进程中实现的某种消息队列——很可能是一个 Windows 服务。

于 2013-03-23T17:47:13.850 回答
0

我找到了答案并且一切正常。 启动长时间后台任务。您可以向 Task StartNew() 方法传递一个参数,该参数指示您正在启动的任务是“长时间运行”的,它为任务调度程序提供了在新线程上启动任务的提示。

var task = Task.Factory.StartNew(Stuff, TaskCreationOptions.LongRunning);

谢谢,medkg15

于 2013-03-30T17:44:54.233 回答