错误访问与从多线程公寓线程模型公寓一个COM DLL时,(Error when accessing

2019-10-16 17:19发布

我有一个第三方应用程序,这样做的唯一的沟通方式就是通过访问所提供的COM组件。 由于互动需要约3分钟这是强制性的,它发生在后台。 所以我试图做的是增加一个参考部件与选项“使嵌入互操作类型” =真,并创建一个测试,通过该接口读取非常基本的数据。 该记录的方式这样做,是由下面的代码:

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的使用这个完美的作品。 接着,我会在第一行代码以下错误:

无法投射型“系统.__ ComObject”的COM对象为接口类型“ICAPILib.System”。 此操作失败的原因是对IID“{1F5EB3E2-35F6-11D2-A191-0060083A260B}”的界面处的COM组件调用QueryInterface失败,因为以下错误:错误加载类型库/ DLL。 (从HRESULT异常:0x80029C4A(TYPE_E_CANTLOADLIBRARY))。

我已经尝试过重新注册组件没有任何成功。

当使用BackgroundWorker线程公寓类型显然是MTA。 COM组件具有的ThreadingModel设置为公寓。 如果我的理解这篇文章http://msdn.microsoft.com/en-us/library/eaw10et3.aspx正确的互操作编组应该采取访问对象的照顾。

没有任何人有什么线索我可以尝试,使这项工作?

Answer 1:

什么happenned的是,COM的Marshaller无法编组的对象。

第一个答案:标准编组需要一个类型库。 这可能是该对象的类型库未正确注册,因此错误。 你是在x86或x64? 尝试注册与REGTLB库。

第二个答案:如果不工作,简单的答案是使用STA的公寓类型的线程。 这可能意味着你不能用一个BackgroundWorker,但可能必须使用完毕时,你摧毁一个专门创建的线程。 如果我们谈论的是一个三分钟的手术,额外的开销可以忽略不计。

注意对象必须从它是要使用的线程上创建,公寓式MSUT是与对象的线程模型的兼容,以避免编组。



Answer 2:

不能使用BackgroundWorker的,它的线程是错误的类型。 这不能改变,它采用了线程池线程,并且始终是MTA。 COM自动创建的STA线程给COM服务器好客家庭和将要造成任何调用来获得封。 不能为该组件工作,它不正确地注册其类型库。 你想要的东西,以避免反正。

相反,您必须创建自己的线程,并调用其SetApartmentState()方法,你开始之前,将其切换到给STA。 您创建该线程上COM对象的实例,否则CLR还是会尝试当元帅的电话也很重要。 从技术上讲,你需要泵消息循环(Application.Run),但你可能会逃脱不需要这么做。 你会发现,如果呼叫死锁或者预期不会触发事件则需要消息循环。



文章来源: Error when accessing a COM dll with Threading Model Apartment from Multithread Apartment