我正在尝试写一个 Browser Helper Object (BHO) 在 C# 中,在单独的线程上操作 DOM。我已经看到其他几个与此相关的问题,答案似乎是“您需要将 DOM 对象从创建它们的线程编码到您的工作线程。”很好的建议,而且非常有道理,但我找不到关于如何执行此操作的 C# 示例。有一些指向需要使用的 P/Invoke API 的模糊指针,但我很难理解如何将其实现到 BHO 中。
我通过示例学习得最好,文档中缺少此类内容的 .NET 示例非常少。有人能给我举个例子吗,在托管代码 BHO 的上下文中,DOM 是通过工作线程操作的?
最佳答案
您不必执行任何手动编码;托管运行时代表您处理任何跨公寓 COM 对象编码(marshal)处理。
这是一个例子;这个示例托管 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
关于C# IE BHO : How do I marshal DOM objects to a worker thread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3105806/