【问题标题】:How can I get more information from Exception (occurring randomly C# WPF)?如何从异常(随机发生 C# WPF)中获取更多信息?
【发布时间】:2012-06-08 21:00:47
【问题描述】:

我们有一个运行在 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 和异步的东西!

那么,如何获得有关异常的更多信息?


编辑:

没有任何 InnerExceptions。

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

【问题讨论】:

  • 是否有未通过电子邮件发送的InnerException
  • 不,所有捕获的异常都将与它们的 InnerExceptions(如果有)一起发送。
  • 您的代码中可能存在异常,该异常被框架中的某些回调隐藏。尝试添加记录异常然后抛出的 catch 子句;它们回到与 WPF 的接触点(例如,在 VM 设置器中,在命令实现中)。此外,如果可能,向该客户端发送匹配的 PDB 并尝试远程调试(使用 Visual Studio 远程调试器)。
  • 您只是通过电子邮件或完整的故障转储获取异常文本吗?后一种情况,将故障转储加载到WinDbg中,加载SOS,执行命令!pe;这将向您显示带有任何内部异常的异常。如果您没有崩溃转储,请让您的客户发送给您。

标签: c# wpf entity-framework exception


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 我们在所有 EF 连接中都有 using 子句。我现在正在做远程调试,我以前从未使用过它,它看起来很有希望。感谢您的回答。我将在可用时更新此线程并提供更多信息。
【解决方案2】:

“ReliableEnter value cannot be null”错误表示您正试图锁定一个设置为 null 的对象。

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

【讨论】:

    【解决方案3】:

    我刚遇到这种情况;就我而言,我过早地处理了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-ing func 返回的 Task,所以信号量太早了 Disposed,我收到了“ReliableEnter value cannot be null”错误。

    【讨论】:

      猜你喜欢
      • 2021-09-26
      • 1970-01-01
      • 2017-06-15
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多