Thread.Sleep SpinWait.SpinUn直到奇怪的行为

时间:2018-10-17 22:49:12

标签: c# multithreading

我有下面的代码。

namespace SandBox
{
    static class Program
    {
        static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
        static void Main()
        {
            Timer timer = new Timer(worker, null, 0, 3000);
            while (true)
            {
                SpinWait.SpinUntil(IsEmpty); //???? freezes up here
                string snippet;
                while (!queue.TryDequeue(out snippet))
                    Thread.Sleep(1);
                Console.WriteLine(snippet);
                Thread.Sleep(5000); //??????
            }
        }
        static void worker(object x)
        {
            queue.Enqueue("***___***___***");
        }

        static bool IsEmpty()
        {
            return queue.IsEmpty;
        }
    }
}

如果我不包括Thread.Sleep(5000);,它将按预期工作。 但是,如果我这样做,它只会输出一行,然后在SpinUntil部分冻结,不再输出任何行。如果我停止它并检查queue.IsEmpty是否为真,则调试器会说它实际上为假! (我确实断断续续地调用了该工作程序,我检查了一个断点。)此外,IsEmpty也得到了调用,并且返回false。

发生了什么事?

1 个答案:

答案 0 :(得分:1)

SpinWait.SpinUntil旋转直到满足指定条件。在这种情况下,条件是IsEmpty,因此它将旋转直到队列为空(或者,如果您愿意,则 while 队列不为空)。

由于等待时间使线程有时间将某些内容放入队列,因此微调器将继续旋转,因为它应该在线程中清空队列,但不能,因为它正在等待微调器

如果更容易理解,SpinUntil(IsEmpty)与说SpinWhile(IsNotEmpty)相同。