这是我当前的代码:我有一个构建excel文件的函数。 该文件只有一个工作簿和一个工作表。 这个过程大约需要10分钟。
我想允许用户取消此过程,而不保存文件。但如果我取消程序excel.exe在任务管理器中徘徊。我该如何优雅地退出该计划?
这是我的简化代码:
# Call getLogger with no args to set up the handler
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(logging.FileHandler('test_log.log', mode='w'))
if __name__ == '__main__':
# call getLogger again with a name to tag subsequent log statements
logger = logging.getLogger(__name__)
logger.info('Importing class')
t = TestClass()
t.make_call()
t.make_another_call()
logger.info('End')
如果用户在此处取消该功能,则是我的代码:尝试优雅地退出
Dim oExcel As Excel.Application = New Excel.Application
oExcel.Workbooks.Add()
Dim sht As New Excel.Worksheet
sht = oExcel.Worksheets.Add
这是releaseObject函数
If BackgroundWorker1.CancellationPending Then
e.Cancel = True
releaseObject(sht)
releaseObject(oExcel.ActiveWorkbook)
releaseObject(oExcel)
oExcel = Nothing
GC.Collect()
Exit Sub
End If
答案 0 :(得分:2)
使用Office互操作没有什么优雅,这就是为什么你应该完全避免它。那里有大量的库支持对Excel电子表格(如NPOI)的DOM级访问。
我看到你对释放COM对象的困难有所了解,但你错过了这里的踢球者:编译器持有对你永远不能释放的临时对象的隐藏引用。另外,你解除了错误的东西。加上Nothing
的设置参数,讽刺的是,没有任何内容。
由于您没有发布所有代码,我无法指出您搞砸了所有代码的所有实例,但第一个例子是:
oExcel.Workbooks.Add()
此处编译器将保留对您永远不会释放的oExcel.Workbooks
的引用。在.NET中使用COM的一个好的经验法则是永远不要使用两个点,并以创建的相反顺序释放所有内容。
您的代码的另一个问题是这一行:
releaseObject(oExcel.ActiveWorkbook)
这就是你在这里阅读有关问题的原因,但有点错过了这一点。调用该属性实际上会返回您需要跟踪和释放的另一个实例,它不会释放以前的活动工作簿对象。
答案 1 :(得分:0)
我最终在这里得到了以下指示: Excel process still runs after closing in VB.net
在创建对象之前,基本上比较所有excel的processID 并在我创建对象后 它是危险的,因为如果用户在这个过程中打开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