C# 将TryDequeue放入while循环安全吗?

C# 将TryDequeue放入while循环安全吗?,c#,task-parallel-library,concurrent-queue,C#,Task Parallel Library,Concurrent Queue,我以前没有使用过并发队列 在while循环中使用如下TryDequeue可以吗?这会不会永远被卡住 var cq = new ConcurrentQueue<string>(); cq.Enqueue("test"); string retValue; while(!cq.TryDequeue(out retValue)) { // Maybe sleep? } //Do rest of code var cq=new ConcurrentQueue(); cq.排队

我以前没有使用过并发队列

在while循环中使用如下TryDequeue可以吗?这会不会永远被卡住

var cq = new ConcurrentQueue<string>();
cq.Enqueue("test");

string retValue;

while(!cq.TryDequeue(out retValue))
{
    // Maybe sleep?
}

//Do rest of code
var cq=new ConcurrentQueue();
cq.排队(“测试”);
字符串值;
而(!cq.TryDequeue(out retValue))
{
//也许睡觉?
}
//完成代码的其余部分

是的,根据文档,它是安全的,但不是推荐的设计

如果队列在第一次调用TryDequeue时是空的,并且在该点之后没有其他线程在队列中推送数据,那么它可能会“永远卡住”(但是,在N次尝试或超时后,您可能会中断while)

ConcurrentQueue让成员检查队列中是否有项目。检查它比在TryDequeue调用上循环要高效得多(特别是当队列通常为空时)

您可能想做的是:

while(cq.IsEmpty())
{
    // Maybe sleep / wait / ...
}

if(cq.TryDequeue(out retValue))
{
...
}
编辑:
如果最后一个调用返回false:另一个线程将该项退出队列。如果没有其他线程,则这是安全的;如果有,则应使用while(TryDequeue)

这是安全的,因为循环实际上不会结束,直到有一个项目被拉出,如果队列有一个项目要取出,则循环最终会结束。如果队列被另一个线程清空,并且没有添加更多的项目,那么循环当然不会结束

除此之外,您还有一个繁忙的循环。事实上,应该始终避免这种情况。您可能会不断轮询队列以请求更多的项目,从而在进程中浪费CPU时间和精力,或者您最终会睡眠,因此在添加项目时不会实际使用队列中的项目(即使如此,仍然会在上下文切换上浪费一些时间/精力来轮询队列)


相反,如果你发现自己处于想要“等到有我要拿的物品”的位置,那么你应该做的是使用
阻止收藏
。它专门设计用于包装各种类型的并发集合和块,直到有一个项目可供使用。它允许您将代码更改为queue.Take(),并且更易于编写,在语义上说明您正在做的事情,使其清晰正确,明显更有效,并且完全安全。

您的意思是不是(!cq.TryDequeue(out-retValue))?@manimoon您是通过多个线程谈论的?我的假设是,在.NET库中专门为并发性设计的队列在这样的while循环中使用是安全的。显然,通过测试,您已经确定在单线程使用中是完全安全的。您的问题表明另一个线程将生成队列项,如果是这种情况,您应该使用BlockingCollection。这里有一个简单的例子:好的,谢谢你——这很有道理。但是如果if(cq.TryDequeue(out-retValue))为false,您应该怎么做呢?这是我关心的问题。编辑中的while()会被卡住吗?