调试与发布C#代码

时间:2018-01-20 19:35:41

标签: c#

我有以下代码:

 public static void Main(string[] args)
    {
        bool isComplete = false;

        var t = new Thread(() =>
        {
            int i = 0;
            while (!isComplete) i += 0;
        });

        t.Start();

        Thread.Sleep(500);
        isComplete = true;
        t.Join();
        Console.WriteLine("complete!");

    }

程序将在释放模式下挂起,并以调试模式提供输出(“完成!”)。

这是什么原因?

感谢。

1 个答案:

答案 0 :(得分:9)

变量isComplete的值很可能被加载到发布版本中的寄存器中,以避免在while循环中从内存中读取值的往返。

因此,当isComplete的值更改为true时,循环将不会“检测”。

你需要向编译器指出这个变量是volatile:基本上告诉系统根据当前线程中执行的代码做出假设,无论这个内存是否发生变化(即,某些其他线程或进程可能会改变它。)

有关详细信息,请参阅此SA答案:

How do I Understand Read Memory Barriers and Volatile - StackOverflow

如果你想深入研究内存和并发性,那么这是Fabian Giesen关于多核系统中缓存一致性的优秀文章:

Cache coherency primer

Atomic operations and contention

除非你知道自己在做什么,否则以下是你应该使用锁的好理由:

Volatile keyword usage vs Lock - StackOverflow

以下是Volatile.Read方法的MSDN文档:

Volatile.Read Method()

请注意,如果没有这些术语的更详细解释(请参阅上面的SA主题或谷歌),MSDN文档中的描述很难转化为实际发生的内容。

以下是volatile关键字的MSDN文档:

volatile (C# Reference)

在C#中,这个关键字将使用半栅栏(据我所知);例如,你也可以在C中找到这个关键字,但它只影响编译器优化(不插入内存屏障),因为它最初用于读取内存映射的I / O.

示例

        bool isComplete = false;

        var t = new Thread(() =>
        {
            int i = 0;
            while (!Volatile.Read(ref isComplete)) i += 0;
        });

        t.Start();

        Thread.Sleep(500);
        isComplete = true;
        t.Join();
        Console.WriteLine("complete!");