【问题标题】:C# IE BHO: How do I marshal DOM objects to a worker thread?C# IE BHO:如何将 DOM 对象编组到工作线程?
【发布时间】:2011-03-07 13:20:18
【问题描述】:

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

我通过例子学得最好,而且文档中缺少此类 .NET 示例。有人可以举一个例子,在托管代码 BHO 的上下文中,DOM 是通过工作线程操作的吗?

【问题讨论】:

  • 你真的不应该编写托管的 IE 扩展。您本机执行此操作的方式是使用 CoMarshallInterThreadInterfaceInStream()。 msdn.microsoft.com/en-us/library/ms693316(VS.85).aspx
  • 当然这不是最佳选择,非托管代码会更好,但 .NET 框架有一堆对我的目的非常有用的类(HttpListener,一个非常简单的 Sockets 实现,等等在)。假设 BHO 旨在用作 QA 人员的测试自动化工具。
  • 借助 .NET 4 Side by Side (SxS) 支持,应该可以创建托管扩展而不会出现此处提到的旧版本问题:msmvps.com/blogs/vcsjones/archive/2010/05/23/…。不过性能可能是个问题。

标签: c# multithreading internet-explorer com bho


【解决方案1】:

您不必执行任何手动编组;托管运行时代表您处理任何跨单元 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

【讨论】:

    猜你喜欢
    • 2010-10-21
    • 2012-05-07
    • 2018-12-14
    • 2012-02-02
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    相关资源
    最近更新 更多