1

我们有一个运行在 WPF 和实体框架之上的大型业务应用程序。问题是我们在过去 2 周内遇到了问题,无法确定问题的根源。

异常被 DispatcherUnhandledException 捕获,我们从异常中获得的信息(通过电子邮件)是这样的:

mscorlib: Value cannot be null.
   at System.Threading.Monitor.ReliableEnter(Object obj, Boolean& lockTaken)
   at System.Threading.Monitor.Enter(Object obj, Boolean& lockTaken)
   at System.Data.EntityClient.EntityConnection.ChangeConnectionString(String newConnectionString)
   at System.Data.EntityClient.EntityConnection.Dispose(Boolean disposing)
   at System.ComponentModel.Component.Finalize()

该异常每天“随机”抛出 4 或 5 次,并且仅来自我们拥有的 20 多个用户中的一个。我们无法弄清楚问题!堆栈跟踪没有提供太多信息,我们无法重现该问题。

我假设这发生在一个线程上,但我无法识别导致异常的线程,因为我们有很多 BackgroundWorkers 和异步的东西!

那么,我怎样才能获得有关异常的更多信息?


编辑:

没有任何内部异常。

此外,异常以分钟和小时为间隔抛出,例如:11:41、11:46、11:51 然后它运行良好,直到 18:03、18:07、18:11 然后没有异常抛出. 该分钟间隔发生的时刻也是随机的,与服务器或网络上的任何负载无关。

4

3 回答 3

3

看起来这可能是作为垃圾收集线程的一部分发生的。堆栈底部的 Finalize 调用是提示,然后可能调用 EntityConnection.Dispose(false);

问题的性质是不确定的。您的环境中可能已经发生了一些变化,它现在正在发生。

在终结器中,访问其他托管对象确实不安全。看起来 ChangeConnectionString 可能正在尝试使用托管对象作为锁,有时当它在 GC 线程中时,对象已经被清理了。它这样做可能是 EntityConnection 中的一个错误。

您应该能够通过在组件上调用 Dispose 来避免这种情况,而不是让 Finalizer 运行(将它们包含在 using 块中是确保这一点的好方法)。但是,使用您拥有的调用堆栈,很难说导致问题的组件的性质。

如果您想获得本地重现,请尝试使用覆盖 Finalize 的类(例如 ~MyComponent())对访问 EntityConnections 的 Component 对象进行子类化并在其中抛出异常。这样,如果 GC 清理了这些对象,您就会崩溃。

于 2012-06-08T22:34:34.490 回答
1

“ReliableEnter 值不能为空”错误意味着您正在尝试锁定设置为空的对象。

查找对象被设置为 null 的位置。

于 2015-09-07T05:17:46.060 回答
1

我刚刚发生了这种情况;就我而言,我处理SemaphoreSlim得太早了。

我的代码类似于

using (var semaphore = new SemaphoreSlim(0, 1))
{
    //... start task that will call semaphore.Release()
    return func(); // this in turn calls semaphore.WaitAsync(timeout);
}

因为我没有await返回Taskby func,所以信号量Dispose太早了,我得到了“ReliableEnter value cannot be null”错误。

于 2020-07-18T09:17:17.143 回答