Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 从新线程处理ExcelDnaUtil.应用程序_Multithreading_Excel_Vb.net 2010_Excel Dna - Fatal编程技术网

Multithreading 从新线程处理ExcelDnaUtil.应用程序

Multithreading 从新线程处理ExcelDnaUtil.应用程序,multithreading,excel,vb.net-2010,excel-dna,Multithreading,Excel,Vb.net 2010,Excel Dna,我正在用ExcelDNA开发一个XLL 在其中,我有一个位于DLL中的表单,我将“ExcelDnaUtil.Application”作为成员传递给它,以促进表单与运行XLL的Excel实例之间的交互 如果我使用以下命令在主线程中启动表单: form1.show() 当我关闭表单然后关闭Excel时,Process Explorer会显示Excel进程已正确处理 如果我使用新线程启动表单: Dim workerThread As Thread workerThread = New Thread(

我正在用ExcelDNA开发一个XLL

在其中,我有一个位于DLL中的表单,我将“ExcelDnaUtil.Application”作为成员传递给它,以促进表单与运行XLL的Excel实例之间的交互

如果我使用以下命令在主线程中启动表单:

form1.show()
当我关闭表单然后关闭Excel时,Process Explorer会显示Excel进程已正确处理

如果我使用新线程启动表单:

Dim workerThread As Thread
workerThread = New Thread(Sub() form1.showdialog())
workerThread.Start()
当我关闭表单,然后关闭Excel时,流程将保留在process Explorer中。我一直很小心,没有在任何代码行中使用两个小数点,并在关闭表单时将接口成员设置为“nothing”。我没有使用“ReleaseCOMObject”,因为其他文章已经指出这是一种不好的做法


问题:如何从单独的线程正确地处理Excel进程?

跨线程处理COM内容是不可能的

永远不要从另一个线程与Excel COM对象模型对话。如果你遵循这条简单的规则,你就永远不必担心两点,永远不必将任何东西设置为零,也不必调用任何ReleaseComObject hack。Excel将很好地关闭

由于Excel是单线程的(实际上是因为Excel COM对象模型位于单线程单元中),因此使用另一个线程与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