在不同的线程中使用mshtml接口

时间:2013-01-17 18:24:11

标签: c# .net com bho mshtml

我用B#编写了BHO。初始化在主线程中的DocumentComplete事件处理程序中执行,然后我启动单独的线程并希望在该线程中使用IMarkupServices但收到以下错误:

  

System.InvalidCastException:无法转换类型的COM对象   'mshtml.HTMLDocumentClass'到接口类型'mshtml.IMarkupServices'。   此操作失败,因为QueryInterface调用COM   与IID接口的组件   '{3050F4A0-98B5-11CF-BB82-00AA00BDCE0B}因以下原因失败   错误:不支持此类接口(HRESULT异常:0x80004002   (E_NOINTERFACE))。

以下是初始化的完成方式:

void ieInstance_DocumentComplete(object pDisp, ref object URL)
{
    InternetExplorer explorer = pDisp as InternetExplorer;
    _ieHtmlDocument2 = (IHTMLDocument2)explorer.Document;
    _markupServices = (IMarkupServices)_ieHtmlDocument2;
    _markupServices.CreateMarkupPointer(out _markupPointerBeginGlob);  // No exception here
    _workerThread = new Thread(WorkerThread);
    _workerThread.IsBackground = true;
    _workerThread.SetApartmentState(Thread.CurrentThread.GetApartmentState());
    _workerThread.Start();
}

这是线程过程:

void WorkerThread()
{
    _markupServices.CreateMarkupPointer(out _markupPointerBeginGlob);  // Exception here!
}

修改 看来在C ++中,有必要调用以下函数来实现我的需求:

CoMarshalInterThreadInterfaceInStream
CoGetInterfaceAndReleaseStream

EDIT2:

尝试显式调用CoMarshalInterThreadInterfaceInStream / CoGetInterfaceAndReleaseStream但仍然没有结果(尝试使用标记服务时抛出相同的异常)

1 个答案:

答案 0 :(得分:1)

为了将IMarkupServices传递给工作线程,接口需要首先实现并可用,并且它也应该是可编组的。您似乎没有后者的运气:接口没有对类型库或自定义代理/存根类的引用。它既不能提供自动代理/存根对。因此,没有可以通过公寓边界。

UPD。这里的重点是,如果你可以将接口传递到另一个线程,那么对象本身将指示基础编组模式(取决于公寓类型,对象的IMarshal实现可用性),无论你是否可以直接从后台线程访问对象,或者将此访问序列化为原始线程。在后一种情况下,编组到工作线程可能会使UI线程响应,但由于编组费用增加,整个处理总体上可能会更慢。在你的情况下,你无法在第一名编组。

基本上你只能选择在原始帖子中使用它。在本机域中,您还可以尝试违反COM准则并将原始指针传递给后台线程并从那里开始使用它。这不能保证工作,我不建议做,但根据对象本身,它有时很好。在托管代码中,这个技巧甚至更少推荐(如果可能的话)。