从后台线程调用COM Interop API?

时间:2011-10-27 01:46:49

标签: c# com task-parallel-library

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

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

我知道这是一个访问冲突异常,我想我并没有以正确的方式捕捉我的对象。

如何从后台线程中调用主线程中创建的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();
}

调用COM对象的方法:

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

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

3 个答案:

答案 0 :(得分:1)

许多旧的COM对象都是在桌面应用程序内运行的。这意味着他们希望在UI线程上运行,Windows消息泵是唯一的同步方法。

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

如果您没有违反这些假设,代码可能会有效,但如果您这样做,那么您将遇到问题(或两个或两个)。

答案 1 :(得分:0)

如果你绝望,你可以产生一个执行com代码的完整的独立进程。然后你必须写 ipc

答案 2 :(得分:-1)

可以在后台运行COM / OLE Interop对象,但必须使用正确的线程模型编译它们

如果是Delphi for MTA,则应编译

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

如果STA默认情况下使用

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

它应该与C / C ++和其他非托管语言类似

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