你猜,在i == 0的情况下,这个程序需要多长时间才能产生第一个输出?应该是瞬间完成了吧?通过yield
的惰性求值,之后会连续快速地产生输出,对吗?
static void Main(string[] args)
{
Stopwatch stopwatch = Stopwatch.StartNew();
int i = 0;
foreach (var item in massiveYieldStatement())
{
if (i++ % 10000 == 0)
Console.WriteLine(stopwatch.ElapsedMilliseconds / 1000);
}
Console.ReadKey();
}
static IEnumerable<string> massiveYieldStatement()
{
yield return "a";
yield return "a";
.. repeat 200,000 times !!
yield return "a";
}
但事实并非如此!它坐在那里,没有输出,持续4到21分钟,然后快速完成 - 在一个案例中低于60ms!在这些分钟中,使用了一个核心的CPU价值100%,并且内存使用量增加。在我遇到这个问题的实际场景中,甚至在第一次迭代之前就会抛出Stackoverflow异常!我已经尝试在Visual Studio的调试模式和从命令提示符中的发行模式中进行了测试。我已经在Windows 7 x64和Windows Server 2008 R2 x64上进行了尝试。
有人能解释这里到底发生了什么吗?你可以重现这个问题吗?
注意:这不是真正的代码:真正的代码yield语句要少得多,但复杂得多。这只是最简单的重现。
switch
语句的情况,导致一些病态行为。您是否有必要使用如此多yield
语句的迭代器呢? - Gabeforeach
。如果第二次非常快,那么很可能是JIT编译的开销导致了你的观察结果。 - Ani