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

查看:122
本文介绍了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)表达式使用不少于三个引用。一个用于由单元属性返回的范围对象,一个用于由 i + 1 选择的子范围对象,另一个用于由 J + 1 。非常好的语法糖由VB.NET语言提供,编写COM代码没有它是很痛苦的痛苦。但没有帮助,让您看到参考。不仅您不能在源代码中看到它,调试器绝对没有什么可以帮助您看到它们。

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天全站免登陆