在asp.net MVC 4中收集修改错误

时间:2012-12-14 09:07:29

标签: c# asp.net-mvc collections error-handling

我试图在我的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)

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

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

1 个答案:

答案 0 :(得分:2)

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

但是从堆栈跟踪中我已经可以看到(MVC)框架(例如System.Web)中发生错误。如果堆栈跟踪指向您自己的代码,则问题通常是由于在迭代它时操纵集合(.e.g删除,添加)(例如在foreach循环中)。一些建议是以反向方式迭代或在集合中使用.ToList(),请参阅: Collection was modified; enumeration operation may not execute Collection was modified; enumeration operation may not execute - why?

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

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

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

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