2

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

System.InvalidCastException:无法将类型为“mshtml.HTMLDocumentClass”的 COM 对象转换为接口类型“mshtml.IMarkupServices”。此操作失败,因为 IID 为“{3050F4A0-98B5-11CF-BB82-00AA00BDCE0B}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(来自 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

编辑2:

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

4

1 回答 1

1

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

UPD。这里的重点是,如果您可以将接口传递给另一个线程,则对象本身将指示底层封送模式(取决于单元类型,对象的IMarshal实现可用性),您是否可以直接从后台线程访问对象,或者此访问将被序列化为原始线程。在后一种情况下,编组到工作线程可能会使 UI 线程响应,但由于编组费用增加,整个处理总体上可能会变慢。在您的情况下,您无法首先编组。

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

于 2013-01-17T22:30:50.960 回答