我实例化一个服务类,其中包含一个执行终端自动化的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...
}
答案 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