Excel进程未在VB.net关闭 [英] Excel Process not closing in VB.net

查看:679
本文介绍了Excel进程未在VB.net关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用interop.excel创建一个excel文件,该过程不关闭。
这是我想要使用的代码。

I am creating an excel file using interop.excel and the process is not closing. This is the code i am trying to use.

 Private Sub converToExcel(fileLoc As String, ds As DataSet)
    Dim xlApp As Excel.Application
    Dim xlWorkBook As Excel.Workbook
    Dim xlWorkBooks As Excel.Workbooks
    Dim xlWorkSheet As Excel.Worksheet
    Dim misValue As Object = System.Reflection.Missing.Value
    Dim i As Integer
    Dim j As Integer

    xlApp = New Excel.Application
    xlWorkBooks = xlApp.Workbooks
    xlWorkBook = xlWorkBooks.Add(misValue)
    xlWorkSheet = xlWorkBook.Sheets("sheet1")

    For i = 0 To ds.Tables(0).Rows.Count - 1
        For j = 0 To ds.Tables(0).Columns.Count - 1
            xlWorkSheet.Columns.NumberFormat = "@"
            xlWorkSheet.Cells(i + 1, j + 1) = String.Format("{0}", ds.Tables(0).Rows(i).Item(j).ToString())
        Next
    Next

    xlWorkSheet.SaveAs(fileLoc)
    xlWorkBook.Close()
    xlApp.Quit()

    releaseObject(xlWorkSheet)
    releaseObject(xlWorkBook)
    releaseObject(xlWorkBooks)
    releaseObject(xlApp)

End Sub
Private Sub releaseObject(ByVal obj As Object)
    Try
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
        obj = Nothing
    Catch ex As Exception
        obj = Nothing
    Finally
        GC.Collect()
    End Try
End Sub

我想我缺少一个COM对象,但似乎找不到一个解决方案。
另外注意,这是在64位Windows 8上运行。
任何帮助将是伟大的!
感谢

I think i am missing a COM object but cant seem to find a solution. Also as a note, this is running on 64-bit Windows 8. Any help would be great! Thanks

推荐答案

这样的手动内存管理永远不会工作。这是一个已经知道很长时间的问题,也是发明垃圾收集器的核心原因。程序员永远忘记释放内存。

Manual memory management like this just never works. This is a problem that's been known for very a long time and the core reason that garbage collectors were invented. Programmers just forever forget to release memory.

看不到正在使用的内存时,会变得非常困难。在您的代码中肯定是这种情况, xlWorkSheet.Cells(i + 1,j + 1)表达式使用不少于三个引用。一个用于由Cells属性返回的范围对象,一个用于由 i + 1 选择的子范围对象,另一个用于由<$ c $选择的子范围对象c> j + 1 。非常漂亮的语法糖提供的VB.NET语言,编写COM代码没有它是相当doggone痛苦。但是没有帮助,让你看到引用。你不能在源代码中看到它,调试器可以做任何事情来帮助你看到它们。

It gets extra hard when you can't see the memory being used. Which is certainly the case in your code, the xlWorkSheet.Cells(i + 1, j + 1) expression uses no less than three references. One for the range object returned by the Cells property, one for a sub-range object selected by i+1 and another for the sub-range object selected by j+1. Very nice syntax sugar provided by the VB.NET language, writing COM code without it is pretty doggone painful. But not helpful to let you see the references. Not only can't you see it in your source code, there is absolutely nothing the debugger can do to help you see them either.

这是一个解决的问题在.NET中,它有一个垃圾收集器,它可以看到一切。最基本的问题是,你不给它一个机会来解决你的问题。您所犯的错误是您已停止。可能通过在最后一个语句上设置断点,然后在任务管理器中查看Excel.exe仍在运行。是的,这是正常的。垃圾收集不是即时

This is very much a solved problem in .NET, it has a garbage collector and it can see everything. The most basic problem is that you don't give it a chance to solve your problem. The mistake you made is that you stopped. Probably by setting a breakpoint on the last statement and then looking in Task Manager and seeing Excel.exe still running. Yes, that's normal. Garbage collection is not instant.

调用GC.Collect()应该是即时的,但是不能在特定的运行您的项目的Debug构建的情况。局部变量的生命期然后扩展到方法的结尾,帮助您在Autos / Locals / Watch窗口中看到它们。换句话说,GC.Collect()实际上不收集任何的接口引用。有关此信息中的行为的详情。

Calling GC.Collect() is supposed to make it instant, but that doesn't work in the specific case of running the Debug build of your project. The lifetime of local variables gets then extended to the end of the method, help you see them in the Autos/Locals/Watch window. In other words, GC.Collect() doesn't actually collect any of the interface references. More about that behavior in this post.

简单的解决方法是不停止。继续做有用的事情,给垃圾收集器一个运行的理由。或者让程序在完成后终止,当终结器线程最后一次运行时,Excel终止。这是因为有引用的局部变量不在范围内了。

The simple workaround is to not stop. Keep doing useful things to give the garbage collector a reason to run. Or letting your program terminate since it is done, Excel terminates when the finalizer thread runs for the last time. Which works because the local variables that had the references are not in scope anymore.

但是每个人都想要立即修复。你通过删除所有的releaseObject()调用来获得它。而这样做代替:

But everybody wants the instant fix anyway. You get it by deleting all the releaseObject() calls. And doing it like this instead:

converToExcel(path, dset)
GC.Collect()
GC.WaitForPendingFinalizers()

或者换句话说,该方法已返回。局部变量不再在范围内,因此它们不能保留到Excel引用。它现在也将工作,当你调试它,像它已经做了当你运行发布版本没有调试器。

Or in other words, force a collection after the method has returned. The local variables are no longer in scope so they can't hold on to an Excel reference. It will now also work when you debug it, like it already did when you ran the Release build without a debugger.

这篇关于Excel进程未在VB.net关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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