.net - 使用 IDisposable 清理 Excel 互操作对象

标签 .net excel vb.net interop com-interop

在我的公司中,发布 Excel Interop 对象的常见方法是按以下方式使用 IDisposable:

Public Sub Dispose() Implements IDisposable.Dispose
    If Not bolDisposed Then
        Finalize()
        System.GC.SuppressFinalize(Me)
    End If
End Sub

Protected Overrides Sub Finalize()
    _xlApp = Nothing
    bolDisposed = True
    MyBase.Finalize()
End Sub

其中 _xlApp 是通过以下方式在构造函数中创建的:

Try
    _xlApp = CType(GetObject(, "Excel.Application"), Excel.Application)
Catch e As Exception
    _xlApp = CType(CreateObject("Excel.Application"), Excel.Application) 
End Try

客户端使用using-statement来执行有关Excel互操作对象的代码。

我们完全避免使用 two dot rule 。现在我开始研究如何发布(Excel)互操作对象以及我发现的几乎所有关于它的讨论,例如 How to properly clean up excel interop objectsRelease Excel Objects主要使用 Marshal.ReleaseComObject(),没有一个使用 IDisposable 接口(interface)。

我的问题是:使用 IDisposable 接口(interface)释放 Excel 互操作对象有什么缺点吗?如果是这样,这些缺点是什么。

最佳答案

Are there any disadvantages using the IDisposable Interace

当然,它绝对一事无成。使用 Using 或调用 Dispose() 从来都不是将变量设置为 Nothing 的合适方法。这就是您的代码所做的全部事情。

We completely avoid to use the two dot rule.

请随意继续忽略它,这是无稽之谈,只会引起悲伤。博客作者隐含的断言是,这样做将迫使程序员使用变量来存储 xlApp.Workbooks 的值。所以他以后就有机会不要忘记调用releaseObject()。但是还有更多的语句生成不使用点的接口(interface)引用。像 Range(x,y) 这样的东西,有一个隐藏的 Range 对象引用,你永远不会看到。必须存储它们只会产生极其复杂的代码。

仅仅忽略一个就足以完全无法完成工作。根本不可能调试。这是 C 程序员必须编写的代码。大型 C 程序经常会发生内存泄漏,并且程序员会花费大量时间来查找这些泄漏,而且经常会惨遭失败。当然不是 .NET 方式,它有一个垃圾收集器来自动执行此操作。它永远不会出错。

问题是,它处理这项工作的速度有点慢。非常符合设计。除了这种代码之外,没有人注意到这一点。您可以看到垃圾收集器没有运行,您仍然看到 Office 程序在运行。当您编写 xlapp.Quit() 时它并没有退出,它仍然存在于任务管理器的“进程”选项卡中。他们希望发生的是当他们这么说时它就会退出。

这在 .NET 中很有可能,您当然可以强制 GC 完成工作:

GC.Collect()
GC.WaitForPendingFinalizers()

繁荣,每个 Excel 对象引用都会自动释放。无需自己存储这些对象引用并显式调用 Marshal.ReleaseComObject(),CLR 会为您完成此操作。而且它永远不会出错,它不使用或不需要“两点规则”,并且可以轻松找到那些隐藏的接口(interface)引用。

<小时/>

然而,最重要的是确切您放置此代码的位置。大多数程序员将其放在错误的位置,就像使用那些 Excel 接口(interface)的方法一样。这很好,但在调试代码时不起作用,这是 this answer 中解释的一个怪癖。 。在博客作者的代码中执行此操作的正确方法是将代码移至一个小辅助方法中,我们将其称为 DoExcelThing()。像这样:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    DoExcelThing()
    GC.Collect()
    GC.WaitForPendingFinalizers()
    '' Excel.exe no longer running anymore at this point
End Sub

请记住,这实际上只是一个调试工件。程序员只是讨厌使用任务管理器来杀死僵尸 Excel.exe 实例。当他们停止调试器时,就会变得僵尸化,阻止程序正常退出并收集垃圾。这是正常。当您的程序因任何原因在生产中终止时也会发生这种情况。把你的精力放在该用的地方,消除代码中的错误,这样你的程序就不会死掉。 GC 不需要更多的帮助。

关于.net - 使用 IDisposable 清理 Excel 互操作对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25134024/

相关文章:

excel - 日期格式 英语/法语

Python openpyxl data_only=True 返回 None

vb.net - 如何使用通配符搜索删除sqlite数据库中的表?

c# - 正则表达式用 <br> 标签替换多个换行符

c# - 对于接口(interface) : T[], IEnumerable<T>、IList<T> 或其他接口(interface),您更喜欢哪个?

c# - 为旧的 JSON 结构添加向后兼容性支持

c# - 如何使用 ASP.NET 从代码后面添加额外的 css 类?

.net - 使用真实IP加密发送到托管在服务器上的WCF服务的消息

python - 初学者 Python : Saving an excel file while it is open

关闭 vb.net 应用程序后 Excel 仍在运行