VB.Net - Excel COM对象未被释放 [英] VB.Net - Excel COM Object not getting released
问题描述
我遇到一个问题,即使在调用ReleaseComObject和GC.Collect方法后Excel Process仍然保持活动状态。
I am facing an issue where Excel Process remains active even after calling ReleaseComObject and GC.Collect method.
我的Excel进程终止,用户表单
下面的示例代码显示了我正在做什么以摆脱Excel Process:
Below is sample code which shows what all things I am doing to get rid of Excel Process:
Public Class frmTEST
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim objExcel As xl.Application
Dim wbReport As xl.Workbook = Nothing
objExcel = CreateObject("Excel.Application")
Try
wbReport = objExcel.Workbooks.Open("D:\EL\Nicolas\VS Online\Classe A v2\Launcher-v2.2\Resources\Modules\Zoom.xlsm")
Catch ex As Exception
Common.WriteDebugLog("Exception line 44")
End Try
If wbReport Is Nothing Then
MsgBox("Erreur d'ouverture du reporting - Code 745.", vbExclamation)
Exit Sub
End If
With objExcel
.Visible = False
.ScreenUpdating = False
.Calculation = xl.XlCalculation.xlCalculationManual
.DisplayAlerts = False
End With
'' Here I do all my processing which I have removed to make the question more simplified
With objExcel
.Calculation = xl.XlCalculation.xlCalculationAutomatic
.ScreenUpdating = True
.DisplayAlerts = True
End With
''~~> Close & Clean Up
wbReport.Close(SaveChanges:=False)
objExcel.Quit()
Me.ReleaseObject(wbReport)
Me.ReleaseObject(objExcel)
MsgBox("Done")
End Sub
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
MsgBox("Final Released obj # " & intRel)
Catch ex As Exception
MsgBox("Error releasing object" & ex.ToString)
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
UPDATE :根据我收到的评论,我对我的代码
进行了更改。其他线程,但它仍然没有帮助。我的Excel
进程终止,但只有在我关闭用户表单后才会终止
UPDATE: Based on comments I received, I made changes in my code following the other thread, but it still doesn't help. My Excel Process terminates but ONLY after I close User Form
推荐答案
正在使用.Net V4或更高版本,请尝试。
将所有 Button1_Click
代码移入子例程,并从 Button1_Click
调用它。这将允许该子例程的本地对象超出范围,从而有资格进行垃圾回收。
If you are using .Net V4 or greater, give this a try.
Move all your Button1_Click
code into a subroutine and call it from Button1_Click
. This will allow the objects that are local to that subroutine to go out of scope and thereby be eligible for garbage collection.
然后调用使用 Marshal.AreComObjectsAvailableForCleanup 函数来确定释放COM对象需要多少个垃圾收集周期。
Then call a cleanup method that uses the Marshal.AreComObjectsAvailableForCleanup function to determine how many garbage collection cycles are required to free the COM objects.
注释
Remarks
如果在具有深度依赖图的托管代码和本地代码之间有很多引用,则需要很长时间来清除所有对象。每次GC运行它将释放一些RCW,这将反过来释放底层的COM对象。然后,这些COM对象将释放其受管引用,并在下次运行GC时使更多对象可用于清理,从而再次启动该过程。
If there are a lot of references between managed and native code with deep dependency graphs it can take a long time for all the objects to clean up. Each time a GC runs it will free up some number of RCWs, which will in turn release the underlying COM objects. Those COM objects will then release their managed references and make more objects available for cleanup the next time a GC runs, which starts the process over again.
AreComObjectsAvailableForCleanup方法提供应用程序的方式,以确定GC.Collect和GC.WaitForPendingFinalizers需要发生多少个循环,以便清理所有内容。
The AreComObjectsAvailableForCleanup method provides a way for the application to determine how many cycles of GC.Collect and GC.WaitForPendingFinalizers need to happen in order to clean everything up.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
ExcelWork()
Cleanup()
End Sub
Private Sub ExcelWork()
Dim objExcel As xl.Application
Dim wbReport As xl.Workbook = Nothing
objExcel = CreateObject("Excel.Application")
Try
wbReport = objExcel.Workbooks.Open("D:\EL\Nicolas\VS Online\Classe A v2\Launcher-v2.2\Resources\Modules\Zoom.xlsm")
Catch ex As Exception
Common.WriteDebugLog("Exception line 44")
End Try
If wbReport Is Nothing Then
MsgBox("Erreur d'ouverture du reporting - Code 745.", vbExclamation)
Exit Sub
End If
With objExcel
.Visible = False
.ScreenUpdating = False
.Calculation = xl.XlCalculation.xlCalculationManual
.DisplayAlerts = False
End With
'' Here I do all my processing which I have removed to make the question more simplified
With objExcel
.Calculation = xl.XlCalculation.xlCalculationAutomatic
.ScreenUpdating = True
.DisplayAlerts = True
End With
''~~> Close & Clean Up
wbReport.Close(SaveChanges:=False)
objExcel.Quit()
MsgBox("Done")
End Sub
Private Sub Cleanup()
Do
GC.Collect()
GC.WaitForPendingFinalizers()
Loop While Marshal.AreComObjectsAvailableForCleanup
End Sub
这篇关于VB.Net - Excel COM对象未被释放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!