我有下面的代码。
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。
发生了什么事?
答案 0 :(得分:1)
SpinWait.SpinUntil
旋转直到满足指定条件。在这种情况下,条件是IsEmpty
,因此它将旋转直到队列为空(或者,如果您愿意,则 while 队列不为空)。
由于等待时间使线程有时间将某些内容放入队列,因此微调器将继续旋转,因为它应该在线程中清空队列,但不能,因为它正在等待微调器
如果更容易理解,SpinUntil(IsEmpty)
与说SpinWhile(IsNotEmpty)
相同。