C# HTML遍历非常慢

C# HTML遍历非常慢,c#,performance,traversal,mshtml,C#,Performance,Traversal,Mshtml,我面临的问题是,使用C#简单地迭代MSHTML元素的速度非常慢。下面是一个通过文档进行迭代的小示例。所有集合都进行了三次。我们有空白WPF应用程序和名为Browser的WebBrowser控件: public partial class MainWindow { public MainWindow() { InitializeComponent(); Browser.LoadCompleted += DocumentLoaded;

我面临的问题是,使用C#简单地迭代MSHTML元素的速度非常慢。下面是一个通过文档进行迭代的小示例。所有集合都进行了三次。我们有空白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);
    }
}
1行和2行之间的性能差异非常可怕。我试图用非托管C++和COM重写相同的代码,根本没有性能问题,非托管代码运行速度快了1200倍。不幸的是,非托管不是一种选择,因为实际项目比简单的迭代更复杂

我知道运行时第一次为每个被引用的HTML元素(COM对象)创建RCW。但是它能那么慢吗?每秒300个项目,100%核心负载为3,2 GHz CPU

上述代码的性能分析:

枚举使用for each而不是document.all.item(索引)的所有元素集合(如果切换到C++,请使用IHTMlementCollection::get\u newEnum)


建议阅读:

性能差的根源是在MSHTML互操作程序集中定义为动态对象的集合项

public interface IHTMLElementCollection : IEnumerable
{
    ...
    [DispId(0)]
    dynamic item(object name = Type.Missing, object index = Type.Missing);
    ...
}
如果我们重写该接口,使其返回IDispatch对象,那么延迟将消失

public interface IHTMLElementCollection : IEnumerable
{
    ...
    [DispId(0)]
    [return: MarshalAs(UnmanagedType.IDispatch)]
    object item(object name = Type.Missing, object index = Type.Missing);
    ...
}
新产出:

Items: 246, Time: 00:00:00.0034520
Items: 246, Time: 00:00:00.0029398
Items: 246, Time: 00:00:00.0029968

你试过使用Html Agility Pack吗?没有,因为这是第三方,我们不需要在项目中“解析”Html,我们需要节点作为对象。我不理解其中的区别。MSHTML解析HTML,HTML敏捷包将节点作为对象提供给您。
Items: 246, Time: 00:00:00.0034520
Items: 246, Time: 00:00:00.0029398
Items: 246, Time: 00:00:00.0029968