c# - 为什么 VS2010 编译器在锁内通过数组的 foreach 迭代中的 yield 会崩溃?

标签 c# .net visual-studio-2010 compiler-construction

一个关于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/

相关文章:

c# - 使用 ToArgb() 后跟 FromArgb() 不会产生原始颜色

c# - 无法在 Service Fabric 的一个 ActorRuntime 中注册两个 Actor

c# - 如何使用 Mono.Cecil 实现 IsAssignableFrom

javascript - 代码完成无法识别来自 OpenLayers js 文件的成员

c# - 多线程后台 worker 设计

.net - 如何将 Win32 API 函数 "ChooseColor "创建的颜色值转换为 css 兼容的 RGB 十六进制值

c# - 设计问题

c# - Expression.Variable() 和 Expression.Parameter() 有什么区别?

c# - 在 C# 中防止用户输入空控制台

wcf - 是否可以从VS2010插件刷新WCF服务引用?