如何从异常(随机发生 C# WPF)中获取更多信息

本文关键字:WPF 获取 信息 异常 随机 | 更新日期: 2023-09-27 18:36:33

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

异常被调度程序UnhandledException捕获,我们从异常(通过电子邮件)获得的信息如下:

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+ 用户之一。我们无法找出问题所在!堆栈跟踪没有提供太多信息,我们无法重现该问题。

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

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


编辑:

没有任何内部异常。

此外,异常以分钟和小时的间隔引发,例如:11:41、11:46、11:

51,然后它运行良好,直到 18:03、18:07、18:11,然后不会引发异常。此分钟间隔发生的时刻也是随机的,与服务器或网络上的任何负载无关。

如何从异常(随机发生 C# WPF)中获取更多信息

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

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

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

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

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

"

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

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

我刚刚发生了这种情况;就我而言,我过早地处理了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,信号灯Dispose得太早了,我收到"ReliableEnter 值不能为空"错误。