.net 4.5 Excel.Application – 如何优雅地取消

这里是我目前的代码:我有一个函数,build立一个Excel文件。 该文件只有一个工作簿和一个工作表。 这个过程大约需要10分钟。

我想让用户取消这个过程,而不保存文件。 但如果我取消该程序excel.exe逗留在任务pipe理器。 如何优雅地退出程序?

这里是我的简化代码:

Dim oExcel As Excel.Application = New Excel.Application oExcel.Workbooks.Add() Dim sht As New Excel.Worksheet sht = oExcel.Worksheets.Add 

如果用户取消这个函数是我的代码:试图优雅地退出

 If BackgroundWorker1.CancellationPending Then e.Cancel = True releaseObject(sht) releaseObject(oExcel.ActiveWorkbook) releaseObject(oExcel) oExcel = Nothing GC.Collect() Exit Sub End If 

这是releaseObject函数

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

使用Office interop没什么优点,这就是为什么你应该完全避免它 。 有很多图书馆支持DOM级访问Excel电子表格(如NPOI)。

我看到你阅读有关释放COM对象的困难,但是你在这里错过了踢球者: 编译器正在隐藏对永远不能释放的临时对象的引用 。 再加上你免费的错误的东西。 加上设置参数为Nothing ,具有讽刺意味的是,什么都没有。

既然你没有发布你所有的代码,我不能指出你搞砸了所有的实例,但是第一个实例是这样的:

 oExcel.Workbooks.Add() 

在这里,编译器将持有一个你永远免费的oExcel.Workbooks的参考。 在.NET中使用COM的一个好的经验法则就是不要使用两个点,并且按照创build的相反顺序释放所有内容。

你的代码的另一个问题是这一行:

 releaseObject(oExcel.ActiveWorkbook) 

这是什么让我发现,你读到这里的问题,但有点错过了这一点。 调用该属性实际上会返回需要跟踪和释放的另一个实例,它不会释放以前的活动工作簿对象。

我在这里结束了以下的指令: 在VB.netclosures之后,Excel进程仍然运行

基本上比较我创build对象之前,所有的Excel的processID和创build对象之后,这是危险的,因为如果用户打开excel在这个过程中,我可能会杀了错误的…但所有其他选项似乎并不适用于我:(

  Private mAllExcelBefore() As Process Private Sub ExcelProcessInit() Try mAllExcelBefore = Process.GetProcessesByName("Excel") Catch ex As Exception End Try End Sub Private Sub CloseExcel() Dim mAllExcelAfter() As Process Dim bFound As Boolean Try mAllExcelAfter = Process.GetProcessesByName("Excel") If mAllExcelAfter.Length > 0 Then For i As Integer = 0 To mAllExcelAfter.Length - 1 bFound = False For j As Integer = 0 To mAllExcelBefore.Length - 1 If mAllExcelAfter(i).Id = mAllExcelBefore(j).Id Then bFound = True Exit For End If Next If Not bFound Then mAllExcelAfter(i).Kill() End If Next End If Catch ex As Exception End Try End Sub