我有一个 C# .netFramework4.8 COM INTEROP 库,它获取数据并将其放入 .pdf 文件中以保存在某处。这涉及 PDFSharp,因为我需要从现有 .pdf 文件中取出页面并将它们包含在新文件中 - 没什么大不了的。我有一个 VB6 应用程序,它实例化这个 COM 对象并提供要包含在新 .pdf 中的数据 - 这里也没什么大不了的。
我遇到的问题是释放资源,即由 PDFSharp 创建的 PDF 文件:
newDoc.Save(newFile);
newDoc.Dispose();
在 VB6 中,我无法删除该文件或覆盖该文件,但我仍然可以读取该文件(也无法在资源管理器中删除/重命名)。我的测试 .netFrmwk 应用程序中没有这个问题。 .pdf 文件在第一次调试期间被绑定,并且在结束调试后不会被释放 - 我必须关闭 VB6 才能解除对文件的锁定。这告诉我,VB6 无限期地持有该资源,即使理论上 VB6 COM 对象为 NULL 并且 PDFSharp 已处置它。
这是我的 VB6 代码:
Dim path As String
Dim file As String
path = txtPath.Text
file = txtFile.Text
Dim tst As New ComDLL.Class
'Set tst = New ComDLL.Class
Dim i As Long
i = tst.GeneratePDF(path, file)
txt_OUT.Text = tst.GetErrorMessage
Set tst = Nothing
这里也没什么特别的......
那么这里出了什么问题?
编辑: 稍微介绍一下我的 COM 组件: 我有一个带有两个方法的类,如上面的 VB6 代码所示。我认为实现析构函数不合适,因为我删除了这些方法中的所有内存引用 - 所以实际上没有什么可以删除的。 我这样做是愚蠢的吗?不可否认,我现在才开始接触 COM 两个星期......
您遇到的问题是,即使在处理 C# COM Interop 库中的
newDoc
对象后,PDF 文件仍保持锁定状态,这可能是由于 .NET 垃圾收集器未立即释放资源造成的。在 .NET 中,资源清理不是确定性的;实现 IDisposable
的对象会在垃圾收集期间被清理,垃圾收集发生的时间不确定。此行为可能会导致文件锁定的持续时间比预期更长。
为了确保资源及时释放,您可以在处置
newDoc
对象后显式强制垃圾回收。出于性能考虑,在典型的 .NET 应用程序中通常不鼓励使用这种方法,但在涉及 COM Interop 与 VB6 的特定场景中,它可以帮助解决文件锁定问题。
newDoc.Save(newFile);
newDoc.Dispose();
newDoc = null;
GC.Collect();
GC.WaitForPendingFinalizers();
在生产代码中,通常最好将应用程序设计为允许垃圾收集器按自己的计划管理内存。然而,在 COM Interop 与 VB6 等场景中,确定性资源管理至关重要,这种方法可能是合适的。