使用IDisposable清理Excel互操作对象

在我的公司中,发布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互操作对象的代码。

我们完全避免使用两点规则。 现在我开始研究如何释放(Excel)互操作对象以及我发现的几乎所有讨论,比如如何正确清理Excel互操作对象或释放Excel对象主要使用Marshal.ReleaseComObject(),但都没有使用IDisposable接口。

我的问题是:使用IDisposable Interace发布excel互操作对象有什么不利之处吗? 如果是这样,这些缺点是什么。


使用IDisposable Interace是否有缺点?

当然,它完全没有成就。 使用Using或者调用Dispose()永远不会将变量设置为Nothing。 这就是你的代码所做的一切。

我们完全避免使用两点规则。

随意继续忽略它,这是无稽之谈,只会导致悲伤。 博客作者暗示的断言是,这样做会迫使程序员使用变量来存储xlApp.Workbooks的值。 所以他有一个战斗机会,以后,不要忘记调用releaseObject()。 但是有更多的语句产生一个不使用点的接口引用。 像Range(x,y)那样,有一个你永远不会看到的隐藏的Range对象引用。 不得不存储它们,只会产生令人难以置信的令人费解的代码。

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

麻烦的是,在处理这项工作时有点慢。 设计非常多。 除了这种代码之外,没有人会注意到这一点。 你可以看到垃圾收集器没有运行,你仍然可以看到Office程序正在运行。 它在写xlapp.Quit()时并未退出,它仍存在于任务管理器的“进程”选项卡中。 他们想要发生的事情是在他们这样说的时候放弃。

这在.NET中是非常可能的,你当然可以迫使GC完成这项工作:

GC.Collect()
GC.WaitForPendingFinalizers()

繁荣时,每个Excel对象参考都会自动发布。 没有必要自己存储这些对象引用,并显式调用Marshal.ReleaseComObject(),CLR为你做。 它永远不会错,它不会使用或需要“双点规则”,并且无法找回隐藏的接口引用。


然而什么重要的一个很大的是什么地方你把这个代码。 大多数程序员把它放在错误的地方,使用那些Excel接口的方法。 这很好,但在调试代码时不起作用,这个答案中解释了一个怪癖。 在博客作者的代码中正确的做法是将代码移动到一个小帮手方法中,我们称之为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实例。 Zombified当他们停止调试器,阻止程序正常退出并收集垃圾。 这个是正常的。 当您的程序由于任何原因而停止生产时也会发生这种情况。 把你的能量放在它所属的地方,从你的代码中获取错误,这样你的程序就不会死亡。 GC不需要更多的帮助。


如果你正在寻找一种更干净的方式,你可以使用Koogra。 它没有太多的额外开销(只有两个DLL你必须包括在你的参考中),你不必处理隐式垃圾收集。

下面的代码是从excel文件中读取10行10列所需的全部内容,而不留下EXCEL32Excel.exe进程。 我在一个月前就遇到了这个问题,并且写了关于如何去做的说明。 比直接处理Excel Interop更容易,更简洁。

Koogra.IWorkbook workbook = Koogra.WorkbookFactory.GetExcel2007Reader("MyExcelFile.xlsx");
Net.SourceForge.Koogra.IWorksheet worksheet = workbook.Worksheets.GetWorksheetByName("Sheet1");

//This will invididually print out to the Console the columns A-J (10 columns) for rows 1-10.
for (uint rowIndex = 1; rowIndex <= 10; rowIndex++)
{
    for (uint columnIndex = 1; columnIndex <= 10; columnIndex++)
    {
        Console.WriteLine(worksheet.Rows.GetRow(rowIndex).GetCell(columnIndex).GetFormattedValue());
    }
}
链接地址: http://www.djcxy.com/p/35655.html

上一篇: Clean up Excel Interop Objects with IDisposable

下一篇: Need Clarification On Answer For Cleaning Up Excel Interop Objects Properly