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.Database
的 IDisposable
实现中的错误,因为异常中列出的两个 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 代码似乎也有问题。
我的 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.Database
的 IDisposable
实现中的错误,因为异常中列出的两个 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 代码似乎也有问题。