【发布时间】:2020-01-18 20:48:13
【问题描述】:
在我的 MVC 应用程序中,超级管理员可以设置任务队列,例如更新数据库。因此,当管理员向队列添加更新时,控制器会启动一个在后台运行的新任务。但是,当您添加一些任务时,应用程序会抛出 System.Threading.ThreadAbortException: Thread was being aborted。此外,堆栈跟踪表明它发生在代码的不同行上。
我还应该补充一点,这些任务使用 EF6 实体与 SQL 服务器一起工作,并且根据堆栈跟踪,它发生在对数据库执行操作之后或期间。由于更新通常很大,我使用db.Configuration.AutoDetectChangesEnabled = false 并每隔 20k 行手动保存更改,处理并重新创建数据库。
堆栈跟踪示例:
2015 年 7 月 15 日星期三下午 5:18:36:[报告] 异常(行:456667;Section6):System.Threading.ThreadAbortException:线程被中止。 在 System.Array.Copy(数组 sourceArray,Int32 sourceIndex,数组 destinationArray,Int32 destinationIndex,Int32 长度,布尔可靠) 在 System.Collections.Generic.List`1.set_Capacity(Int32 值) 在 System.Data.Entity.Core.Metadata.Edm.MetadataCollection`1.SetReadOnly() 在 System.Data.Entity.Core.Metadata.Edm.TypeUsage..ctor(EdmType edmType,IEnumerable`1 方面) 在 System.Data.Entity.Core.Common.CommandTrees.DbExpression..ctor(DbExpressionKind 种类,TypeUsage 类型,布尔 forceNullable) 在 System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.DbExpressionBuilder.PropertyFromMember(DbExpression 实例,EdmMember 属性,字符串 propertyArgumentName) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.GenerateEqualityExpression(DbExpressionBinding 目标,EdmProperty 属性,PropagatorResult 值) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildPredicate(DbExpressionBinding 目标,PropagatorResult referenceRow,PropagatorResult 当前,TableChangeProcessor 处理器,Boolean & rowMustBeTouched) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand(PropagatorResult oldRow,PropagatorResult newRow,TableChangeProcessor 处理器) 在 System.Data.Entity.Core.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode,UpdateCompiler 编译器) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.d__a.MoveNext() 在 System.Linq.Enumerable.d__71`1.MoveNext() 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCommandOrderer..ctor(IEnumerable`1 命令,UpdateTranslator 翻译器) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ProduceCommands() 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update() 在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions 选项,IDbExecutionStrategy executionStrategy,布尔 startLocalTransaction) 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 操作) 在 System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions 选项,布尔型 executeInExistingTransaction) 在 System.Data.Entity.Internal.InternalContext.SaveChanges() 在 MyWebsite.Controllers.AdminPanelController.ApplyUpdate(String filePath, HttpApplicationStateBase context, Int32 saveInterval, Boolean checkRepetitions, String onCollision)
有什么我做错了吗?
【问题讨论】:
-
您是否在并行查询相同的
DbContext? -
每个任务都会创建自己的上下文。
-
这是一项长期运行的任务吗?如果是 asp.net mvc 是错误的地方。 IIS 可以随时终止或关闭 asp.net,具体取决于负载等。我猜这就是原因。
-
我会使用hangfire.io 或quartz-scheduler.net 来安排长时间运行的任务。恕我直言,hangfire 更简单且功能强大。
-
这一定是由于 web 服务在 x 分钟不活动(wrt http 交互)后杀死了 web 应用程序。在 IIS 中,我相信这是 20 分钟。永远不要在 ASP.Net 应用程序中启动长时间运行的任务。这就是制作hangfire 之类的工具的原因(参见之前的评论)。
标签: c# .net asp.net-mvc multithreading entity-framework