修改RouteCollection时,MVC Mini-Profiler会抛出LockRecursionException

时间:2012-04-06 17:51:39

标签: asp.net-mvc asp.net-mvc-routing mvc-mini-profiler

使用MVC MiniProfiler时,我看到一个非常疯狂的错误。间歇性地,我正在处理的网站进入一个状态,每个请求都会导致抛出此异常:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. 
---> System.TypeInitializationException: The type initializer for 'MvcMiniProfiler.MiniProfiler' threw an exception. 
---> System.Threading.LockRecursionException: Write lock may not be acquired with read lock held. 
 This pattern is prone to deadlocks. Please ensure that read locks are released before taking a write lock. 
 If an upgrade is necessary, use an upgrade lock in place of the read lock.
at System.Threading.ReaderWriterLockSlim.TryEnterWriteLockCore(Int32 millisecondsTimeout)
at System.Threading.ReaderWriterLockSlim.TryEnterWriteLock(Int32 millisecondsTimeout)
at System.Web.Routing.RouteCollection.GetWriteLock()
at MvcMiniProfiler.UI.MiniProfilerHandler.RegisterRoutes() 
 in C:\Users\sam\Desktop\mvc-mini-profiler\MvcMiniProfiler\UI\MiniProfilerHandler.cs:line 81
at MvcMiniProfiler.MiniProfiler..cctor() 
 in C:\Users\sam\Desktop\mvc-mini-profiler\MvcMiniProfiler\MiniProfiler.cs:line 241
— End of inner exception stack trace —
at MvcMiniProfiler.MiniProfiler.get_Current()
at TotallyNotOverDrive.Boom.MvcApplication.Application_EndRequest()

错误一直存在,直到应用程序池被回收。看起来不知何故正在举行锁定,这会阻止MiniProfiler尝试注册它的路线。这种情况发生在我没有启动MiniProfiler的请求中,但在Application_EndRequest期间我调用MiniProfiler.Stop(),这似乎导致在访问Current属性时创建MiniProfiler。对于一个简单的解决方案,我修改了EndRequest以使用相同的逻辑来停止探查器作为BeginRequest,因此如果请求不使用探查器,则应该完全避免此错误。在将此代码发送到生产环境之前,我仍想解决实际问题。

我的路由表非常简单,只添加到Application_Start方法中。我们没有使用任何其他可能在启动后修改路由表的第三方代码。我对路由做的唯一可疑的事情就是在表中添加一个自定义路由,但这是一个非常简单的路由,我只需要一些比标准MVC路由更复杂的模式匹配。

我查看了相关的MiniProfiler代码并且看不到任何可能导致锁未发布的内容,所以我假设它是访问RouteTable时ASP.NET和MiniProfiler冲突的组合。我无法可靠地重现这个问题,所以我想知道是否有其他人在路由方面遇到过这样的问题。感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:1)

我想我知道发生了什么,你需要先获得注册的路线。您正在EndRequest期间注册它们,此时管道中可能还有其他请求在路由表上保存读锁定。

路由在MiniProfiler的静态构造函数中注册。如果在Application_Start期间访问MiniProfiler中的任何设置,这将启动将注册路由的静态构造函数。

例如,在注册路线后尝试添加类似的内容。

MiniProfiler.Settings.PopupMaxTracesToShow = 10;