1

我试图在我的 ASP.NET MVC 4 应用程序中找到以下错误的来源。

Exception type: System.InvalidOperationException
Exception message: Collection was modified; enumeration operation may not execute

Stack trace: at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at System.Web.Mvc.MvcHandler.RemoveOptionalRoutingParameters()
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

问题是我有一个集合的所有(少数)地方都在迭代,我没有以任何方式改变集合结构。堆栈跟踪没有太大帮助,因为它不包含对我的代码的任何引用。

我已经阅读了很多关于这个主题的帖子,基本上这就是他们提到的解决方案。有人知道此类问题的其他解决方案吗?有关如何获取有关错误的更多信息的任何提示?

4

1 回答 1

2

nrod,为了完整起见,最好发布您的代码。

但是,从您的堆栈跟踪中,我已经可以看到(MVC)框架(例如 System.Web)中发生了错误。Í如果堆栈跟踪指向您自己的代码,则问题通常是由于在迭代集合时(例如在 foreach 循环中)操作集合(例如删除、添加)。一些建议是以相反的方式进行迭代或在您的集合上使用 .ToList() ,请参阅: 集合已修改;枚举操作可能无法执行 Collection 被修改;枚举操作可能无法执行 - 为什么?

但是,您的堆栈跟踪表明问题出在您的代码对(MVC)框架的调用。此类问题可能是由于在共享自定义实现的 IRouteHandler.GetHttpHandler() 中使用实例成员变量引起的。这是因为实例成员不是线程安全的,如 MSDN 中所述:http: //msdn.microsoft.com/en-us/library/system.web.http.webhost.httpcontrollerroutehandler%28v=vs.108%29.aspx

您的堆栈跟踪表明您确实在使用成员变量。当执行大量并发调用时(例如在生产环境中),可能会发生错误。

您可以通过重构代码以不使用任何实例成员来解决此问题。这可能会导致代码有些单一和重复。例如,当重构为仅使用局部变量时。但是您也可以尝试将使用重构为公共静态成员或静态函数,因为它们是线程安全的。

在自己解决了这个问题之后,我决定最好总是对新代码进行一些负载测试,否则这些问题只会在生产中检测到!

于 2012-12-18T09:49:37.193 回答