我正在使用ExcelDNA开发一个XLL。
在它中,我有一个存在于DLL中的表单,我将"ExcelDnaUtil.Application“作为成员传递给它,以方便运行XLL的表单和实例之间的交互。
如果我使用以下方法在主线程中启动表单:
form1.show()
当我关闭窗体然后关闭Excel时,显示Excel进程已被正确处理。
如果我使用一个新线程启动表单:
Dim workerThread As Thread
workerThread = New Thread(Sub() form1.showdialog())
workerThread.Start()
当我关闭窗体然后关闭Excel时,进程将保留在中。我非常小心,不要在任何代码行中使用两个小数点,并在关闭表单时将接口成员设置为"nothing“。我没有像其他文章指出的那样使用"ReleaseCOMObject“--实践是错误的。
问:我如何正确地从一个单独的线程处理Excel进程?
发布于 2014-08-21 21:16:28
这是不可能得到正确的COM的东西横线。
您不应该从另一个线程与Excel对象模型对话。如果您遵循这条简单的规则,您就不必担心两个点,也不必将任何东西设置为零,也不必调用任何ReleaseComObject黑客。Excel会很好地关闭。
由于Excel是单线程的(实际上是因为Excel对象模型驻留在一个单线程的单元中),与另一个线程对话对性能没有好处--在内部,所有这些都被编组到主线程。
如果您敢从另一个线程与Excel对话,那么任何COM调用都可能在任何时候失败。这是因为Excel仍然处于“活动状态”,可以进入“对象模型挂起”的状态,从而导致所有COM调用失败(即使是COM消息筛选器也无法捕获错误)。Excel何时会进入如此顽固的模式?例如,当用户做一些疯狂的事情,比如点击他们的鼠标按钮。
那么,在您对另一个线程做了一些工作之后,如何调用Excel呢?Excel-DNA有一个助手,当Excel处于COM调用是安全的模式时,它将安排在主线程上完成的工作。您只需使用包含要完成的工作的委托调用ExcelAsyncUtil.QueueAsMacro(...)
。这个调用可以在任何时候从任何线程进行,但是代码只有在准备就绪时才会运行。
一个有点笨拙的例子是:
Public Module MyFunctions
Dim workerThread As Thread
Public Function OverwriteMe() As Object
Dim caller = ExcelDnaUtil.Application.Caller
workerThread = New Thread( _
Sub()
Thread.Sleep(5000)
ExcelAsyncUtil.QueueAsMacro( _
Sub()
caller.Value = "Done!!!"
End Sub)
End Sub)
workerThread.Start()
Return "Doing it..."
End Function
End Module
https://stackoverflow.com/questions/25434845
复制相似问题