当修改RouteCollection时,MVC Mini-Profiler会抛出LockRecursionException异常。

7

在使用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 241End 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 代码,并没有看到任何可能导致锁定未释放的原因,因此我认为这是 ASP.NET 和 MiniProfiler 在访问 RouteTable 时冲突的组合。我无法可靠地重现该问题,因此我想知道是否有其他人在路由方面遇到过类似的问题。谢谢您能提供的任何帮助。
1个回答

1

我认为我知道发生了什么,你需要更早地注册路由。你是在EndRequest期间注册它们的,在这个时候可能有其他请求在管道中,它们正在保持对路由表的读锁定。

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

例如,在注册路由之后添加类似于以下内容的东西。

MiniProfiler.Settings.PopupMaxTracesToShow = 10;


1
我尝试在Application_Start中添加对MiniProfiler.Current的调用,自从做出这个更改后,它就再也没有失败过。由于很难复现,所以我需要更多时间来确认。让我感到困惑的是,它在应用程序已经处理了一些请求之后才失败,因此路由应该已经注册过了。不过也许我们是在应用程序池休眠后捕获到它的,所以它必须重新启动。 - nslowes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接