Foreach循环需要很长时间才能打出
问题描述:
刮掉一个包含大约250个表格部分的网页。 使用华廷和WatinCSSSelectorsForeach循环需要很长时间才能打出
首先,我选择带有属性的“width = 90%”的所有TD标签:
var allMainTDs = browser.CssSelectAll("td[width=\"90%\"]");
然后我做一个foreach循环,坚持变种的内容到一个列表。 int在那里检查循环当前在哪个td标签。
List<Element> eletd = new List<Element>();
int i = 0;
foreach (Element td in allMainTDs)
{
eletd.Add(td);
i++;
Console.WriteLine(i);
}
它相当快地达到了第250个标记。但是,大约需要6分钟(使用StopWatch对象计时)才能进入下一个语句。这里发生了什么?
答
一个foreach
循环大致相当于下面的代码(不完全,但足够接近):
IEnumerator<T> enumerator = enumerable.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
T element = enumerator.Current;
// here goes the body of the loop
}
}
finally
{
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
}
Th你描述的行为指向这段代码的清理部分。调用CssSelectAll
调用结果的枚举器可能有一个沉重的Dispose方法。你可以通过用类似上面的代码替换你的循环来确认,并省略finally块,或设置断点来确认Dispose
需要永久运行。
答
你可以试试这个:
var eletd = new List<Element>(allMainTDs);
答
如果您在.NET 4.0和你的执行环境允许并行性,你可能应该尝试
Prallel.ForEach(..);
@MHTn什么是`下一个语句` – msarchet 2011-02-02 16:27:10
没关系,此刻我有`int i = 0;`并且只是在那里放置一个断点。问题是需要AGES才能在foreach循环之后到达下一行代码,在这种情况下是`int i = 0;`。 – MHTri 2011-02-02 16:28:33
这很可能是CssSelectAll返回的集合的枚举器的Dispose方法,它占用了您的时间。你可以在探查器下运行它吗? – 2011-02-02 16:32:24