清理的Excel互操作与IDisposable的对象 [英] Clean up Excel Interop Objects with IDisposable

查看:270
本文介绍了清理的Excel互操作与IDisposable的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我公司的共同的方式来释放的Excel互操作的对象是使用了IDisposable方式如下:

 公用Sub Dispose()方法实现IDisposable.Dispose
    如果不bolDisposed然后
        最后确定()
        System.GC.Sup pressFinalize(ME)
    结束如果
结束小组

受保护的覆盖子的Finalize()
    _xlApp =无
    bolDisposed = TRUE
    MyBase.Finalize()
结束小组
 

其中, _xlApp 在构造函数中创建下列方式:

 尝试
    _xlApp = CTYPE(GetObject的(Excel.Application),Excel.Application)
卡子E作为例外
    _xlApp = CTYPE(的CreateObject(Excel.Application),Excel.Application)
结束尝试
 

和客户端使用使用语句执行有关Excel的互操作对象code。

我们完全避免使用<一个href="http://www.siddharthrout.com/2012/08/06/vb-net-two-dot-rule-when-working-with-office-applications-2/"相对=nofollow>双点规则。现在我开始研究如何realease(EXCEL)互操作的对象,几乎所有我发现它喜欢的如何正确清理Excel的互操作对象 使用的大多是对Marshal.ReleaseComObject()释放Excel对象,使用IDisposable接口没有。

我的问题是:有没有用了IDisposable Interace释放Excel的互操作对象的任何缺点?如果是这样,这些是什么disatvantages。

解决方案
  

有没有使用了IDisposable Interace任何缺点

当然,它实现绝对没有。使用的使用的或调用Dispose()从来都不是一个合适的方法来设置一个变量为Nothing。这是所有的code一样。

  

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

欢迎继续忽略它,这是胡说八道,只会带来悲伤。博客作者的暗示说法是,这样做会迫使程序员使用一个变量来存储xlApp.Workbooks的价值。于是,他就会有一个战斗的机会,以后,不要忘记调用releaseObject()。但也有许多产生不使用点接口引用多个语句。喜欢的东西范围(X,Y),有一个隐藏的范围对象的引用那里,你永远也看不到。有来存储它们也仅仅产生令人难以置信的令人费解的code。

和俯瞰刚刚的一个的是足够完全无法完成这项工作。根本不可能进行调试。这是什么样的code是C程序员必须写。而往往在失败惨败,大型C程序经常出现内存泄漏和他们的程序员花费了大量的时间寻找这些泄漏。不是.NET方式的过程中,它有一个垃圾收集器来自动执行此操作。它从来没有得到它错了。

麻烦的是,它在接受这份工作的关心有点慢。设计非常多。从来没有人注意到这一点,但在这种code。你可以的的垃圾收集器没有运行,你仍然可以看到Office程序的运行。当你写xlapp.Quit(它没有退出),它仍然是present在任务管理器的进程选项卡。他们希望发生的是为它当他们这么说不干了。

这是非常有可能在.NET中,你当然可以强制GC来完成这项工作:

  GC.Collect的()
GC.WaitForPendingFinalizers()
 

轰的每次的Excel对象引用被自动释放。没有必要存储这些对象引用自己,明确要求对Marshal.ReleaseComObject()时,CLR会为你。它永远不会是错误的,它不使用或需要二点法则,它毫不费力地找到那些隐藏的接口引用了。


要紧的极大不过是完全,你把这个code。而大多数程序员把它放在错误的地方,就是在使用这些Excel的界面同样的方法。这是很好的,但是当你调试code,这是在这个答案解释一个怪癖不起作用。正确的方法来做到这一点,在博客作者的code是移动code到一个小的辅助方法,我们称之为DoExcelThing()。像这样的:

 私人小组的button1_Click(BYVAL发件人为System.Object的,BYVALË作为System.EventArgs)把手Button1.Click
    DoExcelThing()
    所以GC.Collect()
    GC.WaitForPendingFinalizers()
    ''Excel.exe中不再在这一点上运行了
结束小组
 

和千万记住,这是真正的一切只是一个调试神器。程序员只是不愿意需要使用任务管理器杀僵尸Excel.exe中的实例。当他们停止了调试器,$ P $无法正常退出pventing程序和收集垃圾Zombified。这是的正常的。当你的程序在生产中死亡的任何一种原因也不会发生。把你的精力在它所属,让虫子从你的code使你的程序就不会死。 GC没有需要比这更多的帮助。

In my company the common way to release Excel Interop Objects is to use IDisposable the following way:

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

where _xlApp was created in the constructor the following way:

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

And the client uses the using-statement to execute code concerning excel interop objects.

We completely avoid to use the two dot rule. Now I started researching how to realease (Excel) Interop Objects and almost all discussions I found about it like How to properly clean up excel interop objects or Release Excel Objects are using mostly Marshal.ReleaseComObject(), none of them using the IDisposable Interface.

My questions is: Are there any disadvantages using the IDisposable Interace for releasing excel interop objects? If so, what are these disatvantages.

解决方案

Are there any disadvantages using the IDisposable Interace

Sure, it accomplishes absolutely nothing. Using Using or calling Dispose() is never an appropriate way to set a variable to Nothing. Which is all that your code does.

We completely avoid to use the two dot rule.

Feel free to continue to ignore it, it is nonsense and causes nothing but grief. The blog author's implied assertion is that doing so would force the programmer to use a variable to store the value of xlApp.Workbooks. So he'd have a fighting chance, later, to not forget to call releaseObject(). But there are many more statements that produce an interface reference that don't use dots. Something like Range(x,y), there's a hidden Range object reference there that you'll never see. Having to store them as well just produces incredibly convoluted code.

And overlooking just one is enough to completely fail to get the job done. Utterly impossible to debug. This is the kind of code that C programmers have to write. And often failed at miserably, large C programs often leak memory and their programmers spend a great deal of time finding those leaks. Not the .NET way of course, it has a garbage collector to do this automatically. It never gets it wrong.

Trouble is, it is a bit slow at taking care of the job. Very much by design. Nobody ever notices this, except in this kind of code. You can see that the garbage collector didn't run, you still see the Office program running. It didn't quit when you wrote xlapp.Quit(), it is still present in the Processes tab of Task Manager. What they want to happen is for it to quit when they say so.

That's very possible in .NET, you can certainly force the GC to get the job done:

GC.Collect()
GC.WaitForPendingFinalizers()

Boom, every Excel object reference gets released automatically. There is no need to store these object references yourself and explicitly call Marshal.ReleaseComObject(), the CLR does it for you. And it never gets it wrong, it doesn't use or need a "two dot rule" and it has no trouble finding those hidden interface references back.


What matters a great deal however is exactly where you put this code. And most programmers put it in the wrong place, in the same method that used those Excel interfaces. Which is fine, but does not work when you debug the code, a quirk that's explained in this answer. The proper way to do it in the blog author's code is to move the code into a little helper method, let's call it DoExcelThing(). Like this:

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

And do keep in mind that this is truly all just a debugging artifact. Programmers just hate to have to use Task Manager to kill the zombie Excel.exe instances. Zombified when they stopped the debugger, preventing the program from exiting normally and collect garbage. This is normal. It will also happen when your program dies in production for any kind of reason. Put your energy where it belongs, getting the bugs out of your code so your program won't die. The GC doesn't need more help than that.

这篇关于清理的Excel互操作与IDisposable的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆