2011-10-27 59 views
-1

我实例化一个服务类,它包含一个执行终端自动化的COM互操作组件。我正在使用Microsoft的任务库(TPL)。我想从TPL任务(后台线程)调用COM对象,以便在COM对象工作时我的UI不冻结。从后台线程调用COM Interop API?

但是,当我从后台线程(它接收一个IntPtr)调用我的第一个函数时抛出一个COM异常详细HRESULT:0xC0000005。

我知道这是一个访问冲突异常,我认为我没有用正确的方式来掠夺我的对象。

如何从后台线程在主线程中创建的COM对象调用方法?调用COM对象

public void Button1_Click(object sender, EventArgs e) 
{ 
    var comWrapper = new COMWrapper(); // A simple wrapper for a COM object 

    Task.Factory 
     .StartNew(() => LoadStuff(comWrapper)) 
     .ContinueWith(() => { 
      // Output results... 
     }); 
} 

int LoadStuff(COMWrapper w) 
{ 
    return w.LoadStuffFromCOM(); 
} 

方法:作了

int LoadStuffFromCOM() 
{ 
    string buffer; 
    IntPtr pointer = Marshal.StringToHGlobalUni(buffer); 

    return comObject.GetValue(pointer); // Exception here... 
} 
+0

COM异常'0xC0000005'是'访问denied'。这是一个特权错误。由于您没有发布代码,因此很难找出可能导致它的原因。 “当我打电话给我的第一个功能”并不值得继续时,恐怕。你可以编辑你的问题提供更多的细节? –

+0

我从后台线程调用一个函数。它接收一个从COM输出一些值的IntPtr。如果我在主线程上运行它,它工作得很好。 –

+0

对不起,只是因为我不允许这样做,所以我不能提供很多代码。 –

回答

-1

它可以对后台运行的COM/OLE互操作的对象,但他们必须有正确的线程模型

被编译在Delphi的情况下MTA它应该是默认编译

initialization 
    TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic, 
    ciMultiInstance, tmFree); 
end. 

在STA的情况下,它使用

initialization 
    TTypedComObjectFactory.Create(ComServer, TSomeLogic, Class_SomeLogic, 
    ciMultiInstance, tmApartment); 
end. 

应该simmilar在C/C++和其他非托管语言

的更多信息可以在这里找到: http://msdn.microsoft.com/en-us/library/ff647812.aspx#scalenetchapt07 _topic11

1

许多传统的COM对象,一个桌面应用程序内运行。这意味着他们希望在UI线程上运行,并将Windows消息泵作为唯一的同步方法。

你现在正试图在它可能从未听说过的环境中运行该代码。您很可能违反了作者在编写代码时所作的假设。

如果你没有违反假设,代码可能会工作,但如果你这样做,那么你将有一个问题(或两个,或两打)。

0

如果你绝望,你可能会产生一个执行com代码的单独进程。然后,你会必须写IPC