一个关于Visual Studio 2010中使用的C#/.NET编译器的问题:同事在开发项目的过程中,遇到了在锁内使用现有代码时VS2010编译器崩溃的情况。我们逐行分解代码,最终得出结论:通过 lock 语句中的数组在 foreach
中使用 yield return
会使编译器崩溃。可以使用以下代码重现该问题:
using System;
using System.Collections.Generic;
namespace PlayGround
{
public static class Program
{
private static readonly object SyncRoot = new object();
private static IEnumerable<int> EnumerableWithLock()
{
lock (SyncRoot)
{
foreach (var i in new int[1])
{
yield return i;
}
}
}
public static void Main()
{
foreach (var i in EnumerableWithLock())
{
Console.WriteLine(i);
}
}
}
}
我们继续在 Visual Studio 2013 上测试这个复制示例,它没有出现同样的问题。这个编译器问题似乎与 VS2010 中使用的编译器有关,在 VS2012 中可能有也可能没有同样的问题(出于测试目的我们无法访问它)。此外,我们已经测试过使用常规 for
循环不会崩溃。因此,问题是,为什么 VS2010 编译器会崩溃?它到底在做什么让它如此困惑?
(是的,这主要是出于兴趣了解编译器的问题)
最佳答案
好吧,这可能无法解决问题,但这是我的研究..
理论上,Jon Skeet 说 yield 在与锁一起使用时不会产生任何问题,因为锁分别在第一个和最后一个“MoveNext”迭代 block 之前和之后获取和释放。
更多信息 here .
当我亲自尝试您的代码时,编译器抛出以下(内部)错误:
Error 6 Internal Compiler Error (0xc0000005 at address 1332695D): likely culprit is 'TRANSFORM'.
An internal error has occurred in the compiler. To work around this problem, try simplifying or changing the program near the locations listed below. Locations at the top of the list are closer to the point at which the internal error occurred. Errors such as this can be reported to Microsoft by using the /errorreport option.
ConsoleApp1
但是,对类的以下修改有效:
public static class Program
{
//private static readonly object SyncRoot = new object();
//private static IEnumerable<int> EnumerableWithLock()
//{
// lock (SyncRoot)
// {
// foreach (var i in new int[1])
// {
// yield return i;
// }
// }
//}
public static void Main()
{
SomeClass sc = new SomeClass();
foreach (var i in sc.EnumerableWithLock())
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
public class SomeClass
{
private static readonly object SyncRoot = new object();
int[] i = { 1, 2, 3, 4, 5 };
List<int> retval = new List<int>();
public IEnumerable<int> EnumerableWithLock()
{
lock (SyncRoot)
{
foreach (var number in i)
{
retval.Add(number);
}
return retval;
}
}
}
所以它可能只是一个 CSC 错误 或更微妙的东西。
关于c# - 为什么 VS2010 编译器在锁内通过数组的 foreach 迭代中的 yield 会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25056073/