0

I have this code which loops over an element's nodes:

public static IEnumerable<IHTMLDOMNode> AllElements(this IHTMLDOMNode node)
{
    if (node.IsHTMLElement())
    {
        IHTMLElement element = (IHTMLElement)node;
        IHTMLElementCollection collection = element.all;
        int length = collection.length;
        for (var i = 0; i < length; i++)
        {
            IHTMLDOMNode item = collection.item(i);
            yield return item;
        }
    }
}

My problem is that sometimes, the collection's length will change during the looping. I placed a breakpoint at yield return item; that would break whenever item is null, and noticed when it stopped (and therefore item was null) that my length variable was 815, collection.length was 814 and i was 814 so it was trying to get an item outside the range.

I know I could probably put collection.length inside the loop but I'm afraid this might not solve the root of the problem. Is this supposed to be possible? Is it possible for a script in the page to run at the same time my loop is running which would be the script that is removing an element inside? Or what else could be causing the collection's length to change?

Juan
  • 15,274
  • 23
  • 105
  • 187

2 Answers2

0

Do you have a separate thread which is modifying the collection? Or are you changing it after you retrieve the original enumerator? If you do something like this:

var all = node.AllElements();
node.removeChild(child);
all.moveNext();

You will encounter problems.

Steve Westbrook
  • 1,698
  • 2
  • 20
  • 21
0

The data is live, and can be garbage-collected in the middle of the loop. Calling GC.KeepAlive on the data after the loop should allow it to remain available.

L. Mills
  • 486
  • 4
  • 12