我一直试图弄清楚我的代码中是如何发生错误的。异常告诉我提交已在进行中,但除非对SaveChanges
的调用是异步的,否则我看不出这是怎么回事。
我有一个Scheduler
类,它包含多个Task
个对象。
每个Task
都有一个BackgroundWorker
,可以在另一个线程中处理。然后,我在Task
类中为此BackgroundWorker完成事件创建了一个事件处理程序,其代码如下:
private void TaskWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!(e.Result is TaskResult))
throw new ArgumentException("Result must be a TaskResult class.");
TaskComplete((TaskResult)e.Result);
}
还在我身边吗?所以我在我的任务类中有这个事件处理程序,它使用以下代码触发我在主TaskComplete
类中处理的事件Scheduler
:
private void TaskCompleted(object sender, TaskCompletedEvent e)
{
Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
TaskLog logMsg = new TaskLog()
{
//stuff here
};
scheduledTask.TaskLogs.Add(logMsg);
entitySet.SaveChanges();
}
现在在这一点上,根据我的理解,我回到主线程中,因为我的后台工作人员完成的工作已经完成。当我经常运行5个任务时,我在SaveChanges上得到一个例外,说提交已在进行中。我不明白这是怎么回事,因为我没有跨线程分享这个上下文。我能看到这种情况的唯一方法是SaveChanges是异步的(不是阻塞调用)。我知道使用using语句将TaskCompleted中的代码包装起来,新的上下文会修复它,但我想知道原因。为什么不在目前的状态下工作。
最后一件事,我正在使用Telerik的OpenAccess ORM。
答案 0 :(得分:0)
尝试同步这样的提交:
private static object _syncObject = new object();
private void TaskCompleted(object sender, TaskCompletedEvent e)
{
Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
TaskLog logMsg = new TaskLog()
{
//stuff here
};
scheduledTask.TaskLogs.Add(logMsg);
lock(_syncObject){
entitySet.SaveChanges();
}
}
答案 1 :(得分:0)
您可能在多个主题之间共享DbContext
。
如果您想在多线程环境中使用数据库,那么在开始处理对象之前分离对象(即不使用代理或延迟加载)可能会更好。然后,只需为每个任务创建一个新的DbContext
,附加该对象,然后保存更改。
DbContext
上下文,您应该保留一些计数器,该计数器会因每项任务而增加,然后在每项任务完成时减少。最后,只有在计数器再次达到零时才保存更改。