我面临着使用 C# 简单地遍历 MSHTML 元素的速度非常慢。这是通过document.all集合迭代三次的小例子。我们有空白的 WPF 应用程序和名为 Browser 的 WebBrowser 控件:
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Browser.LoadCompleted += DocumentLoaded;
Browser.Navigate("http://google.com");
}
private IHTMLElementCollection _items;
private void DocumentLoaded(object sender, NavigationEventArgs e)
{
var dc = (HTMLDocument)Browser.Document;
_items = dc.all;
Test();
Test();
Test();
}
private void Test()
{
var sw = new Stopwatch();
sw.Start();
int i;
for (i = 0; i < _items.length; i++)
{
_items.item(i);
}
sw.Stop();
Debug.WriteLine("Items: {0}, Time: {1}", i, sw.Elapsed);
}
}
输出是:
Items: 274, Time: 00:00:01.0573245
Items: 274, Time: 00:00:00.0011637
Items: 274, Time: 00:00:00.0006619
1 和 2 行之间的性能差异是可怕的。我尝试用非托管 C++ 和 COM 重写相同的代码,并且完全没有性能问题,非托管代码的运行速度快了 1200 倍。不幸的是,非托管不是一种选择,因为真正的项目比简单的迭代更复杂。
我知道运行时第一次为每个引用的 HTML 元素(即 COM 对象)创建 RCW。但它会那么慢吗?每秒 300 个项目,100% 核心负载为 3,2 GHz CPU。
上面代码的性能分析: