Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
C# 从多线程单元访问具有线程模型单元的COM dll时出错_C#_Multithreading_Visual Studio 2010_Com_Com Interop - Fatal编程技术网

C# 从多线程单元访问具有线程模型单元的COM dll时出错

C# 从多线程单元访问具有线程模型单元的COM dll时出错,c#,multithreading,visual-studio-2010,com,com-interop,C#,Multithreading,Visual Studio 2010,Com,Com Interop,我必须与第三方应用程序通信,唯一的方法是访问提供的COM组件。因为交互大约需要3分钟,所以必须在后台进行。 所以我试图做的是在组件中添加一个引用,选项“Embedded interop types”=true,并创建一个通过接口读取非常基本数据的测试。记录的方法是通过以下代码: System sys = new System(); if(Convert.ToBoolean(sys.Initialize()) && Convert.ToBoolean(sys.Login("John

我必须与第三方应用程序通信,唯一的方法是访问提供的COM组件。因为交互大约需要3分钟,所以必须在后台进行。 所以我试图做的是在组件中添加一个引用,选项“Embedded interop types”=true,并创建一个通过接口读取非常基本数据的测试。记录的方法是通过以下代码:

System sys = new System();
if(Convert.ToBoolean(sys.Initialize()) && Convert.ToBoolean(sys.Login("John Smith", out userInstance)))
Project proj = new Project();
if (Convert.ToBoolean(proj.Open(sys, m_projName, m_scenarioName)))
    someValue = proj.Name;
在使用BackgroundWorker之前,这一点非常有效。然后在第一行代码中出现以下错误:

无法将“System.\u ComObject”类型的COM对象强制转换为接口类型“ICAPILib.System”。此操作失败,因为对IID为“{1F5EB3E2-35F6-11D2-A191-0060083A260B}”的接口的COM组件的QueryInterface调用由于以下错误而失败:加载类型库/DLL时出错。(来自HRESULT的异常:0x80029C4A(类型为E)

我已经尝试重新注册该组件,但没有成功

当使用BackgroundWorker时,线程单元类型显然是MTA。COM组件已将ThreadingModel设置为单元。如果我理解这篇文章 正确地说,互操作编组应该负责访问对象


有人知道我能做些什么吗?

发生的是COM封送器无法封送对象

第一个答案:标准编组需要类型库。可能是对象的类型库没有正确注册,因此出现错误。您是使用x86还是x64?尝试向REGTLB注册库

第二个答案:如果这不起作用,简单的答案是使用STA单元类型的线程。这可能意味着您不能使用BackgroundWorker,但可能必须使用一个特殊创建的线程,该线程在完成后将被销毁。如果我们谈论的是三分钟的操作,那么额外的开销可以忽略不计


注意:必须在使用对象的线程上创建对象,单元类型msut必须与对象的线程模型兼容,以避免封送。

发生的情况是COM封送器无法封送对象

第一个答案:标准编组需要类型库。可能是对象的类型库没有正确注册,因此出现错误。您是使用x86还是x64?尝试向REGTLB注册库

第二个答案:如果这不起作用,简单的答案是使用STA单元类型的线程。这可能意味着您不能使用BackgroundWorker,但可能必须使用一个特殊创建的线程,该线程在完成后将被销毁。如果我们谈论的是三分钟的操作,那么额外的开销可以忽略不计


注意:必须在使用对象的线程上创建对象,单元类型msut必须与对象的线程模型兼容,以避免编组。

不能使用BackgroundWorker,其线程类型错误。无法更改,它使用线程池线程,并且始终是MTA。COM自动创建一个STA线程,为COM服务器提供一个好客的家,这将导致任何调用被封送。它不能用于该组件,它没有正确注册其类型库。你无论如何都要避免的事情


您必须创建自己的线程,并在启动之前调用其SetApartmentState()方法将其切换到STA。在该线程上创建COM对象的实例也很重要,否则CLR仍将尝试封送调用。从技术上讲,您需要启动一个消息循环(Application.Run),但您可能不需要这样做。您会发现,如果调用死锁或预期事件未触发,则需要消息循环。

您不能使用BackgroundWorker,它的线程类型错误。无法更改,它使用线程池线程,并且始终是MTA。COM自动创建一个STA线程,为COM服务器提供一个好客的家,这将导致任何调用被封送。它不能用于该组件,它没有正确注册其类型库。你无论如何都要避免的事情


您必须创建自己的线程,并在启动之前调用其SetApartmentState()方法将其切换到STA。在该线程上创建COM对象的实例也很重要,否则CLR仍将尝试封送调用。从技术上讲,您需要启动一个消息循环(Application.Run),但您可能不需要这样做。您会发现,如果调用死锁或预期事件未触发,则需要消息循环。

我使用X86(任何构建设置也是如此)。问题是该接口没有提供一个。tlb@Robert-不要追踪错误消息,您无法修复注册过程。修复真正的问题,使用正确类型的线程,因此根本不需要封送。是的,我有点希望它能与MTA一起工作,因为当项目仍然是dotNet 2.0时,它工作得很好,但在X86上使用STAI'm(以及任何构建设置)时它工作得很好。问题是该接口没有提供一个。tlb@Robert-不要追踪错误消息,您无法修复注册过程。修复真正的问题,使用正确类型的线程,因此根本不需要封送。是的,我有点希望它能与MTA一起工作,因为当项目仍然是dotNet 2.0时,它工作得很好,但与STA一起工作就很好