C#IE BHO:如何将DOM对象封送到工作线程?

时间:2010-06-23 21:46:39

标签: c# multithreading internet-explorer com bho

我正在尝试在C#中编写一个Browser Helper Object(BHO),它在一个单独的线程上操作DOM。我已经看到了与此相关的其他几个问题,答案似乎是“你需要将DOM对象从它们创建的线程编组到你的工作线程中。”很好的建议,这很有道理,但我找不到关于如何做到这一点的C#示例。对于需要使用的一些P / Invoke API有一些模糊的指针,但我很难看到如何将其实现为BHO。

我通过示例学到了最好的东西,而且文档中缺少.NET这类例子的例子。有人能指出一个例子,在托管代码BHO的上下文中,DOM是通过工作线程操纵的吗?

1 个答案:

答案 0 :(得分:3)

你不应该进行任何手动编组;托管运行时代表您处理任何跨公寓COM对象编组。

这是一个例子;此样本管理BHO等待,直到DocumentComplete事件触发并旋转一个等待一秒钟的ThreadPool后台线程,然后将页面标题更改为“Hello,StackOverflow!”并添加一个带有特殊消息的新文本节点:

private void OnDocumentComplete(object frame, ref object urlObj)
{
    System.Threading.ThreadPool.QueueUserWorkItem((o) =>
    {
        System.Threading.Thread.Sleep(1000);
            HTMLDocument document = (HTMLDocument)this.browser.Document;
            document.title = "Hello, StackOverflow!";

            IHTMLDOMNode greetings = document.createTextNode("Hi there!");

            IHTMLDOMNode body = document.body as IHTMLDOMNode;
            body.insertBefore(greetings, body.firstChild);                
    }, this.browser);
}

#region IObjectWithSite Members

int IObjectWithSite.SetSite(object site)
{
    if (site != null)
    {
        this.browser = (WebBrowser)site;
        this.browser.DocumentComplete +=
         new DWebBrowserEvents2_DocumentCompleteEventHandler(
          this.OnDocumentComplete);
    }
    else
    {
        if (this.browser != null)
        {
            this.browser.DocumentComplete -=
             new DWebBrowserEvents2_DocumentCompleteEventHandler(
              this.OnDocumentComplete);
            this.browser = null;
        }
    }
    return 0;
}

int IObjectWithSite.GetSite(ref Guid guid, out IntPtr ppvSite)
{
    IntPtr punk = Marshal.GetIUnknownForObject(this.browser);
    int hr = Marshal.QueryInterface(punk, ref guid, out ppvSite);
    Marshal.Release(punk);

    return hr;
}

#endregion