ObjectDisposedException - 无法访问已处置的对象

ObjectDisposedException - Cannot access a disposed object

我的 WPF Windows C# 应用程序有一些问题。每当应用程序关闭时,它都会抛出 System.ObjectDisposedException。该问题似乎只在以 32 位编译时出现。 64 位构建运行良好,没有抛出任何异常。

从异常消息来看,它说无法访问已处置的对象,但它似乎没有说明是什么对象导致了问题 - 如何找出已处置的对象?

Exception:Thrown: "Cannot access a disposed object." (System.ObjectDisposedException) A System.ObjectDisposedException was thrown: "Cannot access a disposed object." Time: 1/19/2016 5:16:28 PM Thread:[1552]

Exception Info: System.ObjectDisposedException Stack: at System.Diagnostics.EventLogInternal.OpenForWrite(System.String) at System.Diagnostics.EventLogInternal.InternalWriteEvent(UInt32, UInt16, System.Diagnostics.EventLogEntryType, System.String[], Byte[], System.String) at System.Diagnostics.EventLogInternal.WriteEntry(System.String, System.Diagnostics.EventLogEntryType, Int32, Int16, Byte[]) at System.Diagnostics.EventLog.WriteEntry(System.String, System.Diagnostics.EventLogEntryType) at HP.HPTRIM.SDK.TrimApplicationBase.UnregisterStackTrace(System.Object, Int32) at HP.HPTRIM.SDK.Database.internal_Dispose() at HP.HPTRIM.SDK.Database.Finalize()

如果您查看堆栈跟踪的最后一行,您会发现问题是由 HP.HPTRIM.SDK.Database 对象的 Dispose() 引起的。

这不是一个很好的答案,因为它太长而无法在评论中呈现。

我在 ILSpy 中花了一些时间查看 EventLog class。异常中最内层的方法 EventLogInternal.OpenForWrite 旨在在设置其内部标志之一时显式抛出 ObjectDisposedException。 (尽管您收到的 ObjectDisposedException 总是有可能不是专门来自这一行的,但值得注意的是。)

private void OpenForWrite(string currentMachineName)
{
    if (this.boolFlags[256])
        throw new ObjectDisposedException(base.GetType().Name);
    ...
}

它检查的标志仅在 EventLog 实例的 Dispose 方法被调用时设置,这意味着 EventLog 实例正在主动处理。由于这是您无法控制的事情,这可能是 HP TRIM 的 HP.HPTRIM.SDK.DatabaseIDisposable 实现中的错误,因为异常中列出的两个 HP 方法之一会成立对 EventLog 实例的引用。

还值得注意的是,可能会触发此异常,因为 HP.HPTRIM.SDK.Database 实例在应用程序关闭期间未被正确处理(假设其 IDisposable)并且只是被允许从范围。作为测试,您可以尝试在应用程序关闭期间以外的某个时间处理您的 HP.HPTRIM.SDK.Database 实例,看看是否可以重现错误。

这与位数有什么关系,我不能说。

可能为时已晚,但我无意中发现了这一点,因为我最近在使用 HP Records Manager SDK(在我的例子中是 v8.3)时遇到了一个非常相似(相同?)的问题。我相信我已经确定了原因。

我自己的代码(使用 HP .Net SDK 连接到 HPRM 的可执行文件)中存在错误,我没有在其中一个 SDK 对象上调用 Dispose()

似乎当 GC 随着可执行文件的退出进行清理时,HP 决定要向 Windows 应用程序事件日志写入一条消息,指出开发人员忘记了对象的 .Dispose() 正确。但是,无论出于何种原因,HP SDK 中似乎也存在一个错误,此时,它会处理其内部系统以写入事件日志。 (有时它对我有用,有时对我不起作用。可能是 SDK 中某处的竞争条件。)

结果是,在我的代码结束后,.Net Framework 跳起来并尖叫着 HP SDK 试图使用已处置的对象来写入事件日志。

我的直接解决方法是修复我自己的代码。一旦我处理了所有我打算处理的对象(特别是我创建的数据库连接),事件链就没有开始。不过,实际上,HP 代码似乎也有问题。