受我当前问题的启发,这与此类似:
Analogue of Queue.Peek() for BlockingCollection when listening to consuming IEnumerable<T>区别于我 - 目前正在使用ConcurrentQueue<T>
而不是BlockingCollection<T>
,我想知道ConcurrentQueue<T>.TryPeek()
的任何用例可能是什么?
当然,我的意思是没有手动lock(myQueue)
内容的用例来序列化队列访问,因为TPL旨在改进/替换这些锁定。
答案 0 :(得分:8)
我有一个使用ConcurrentQueue<T>.TryPeek
效果很好的应用程序。设置了一个线程来监视队列。它主要是关注队列大小,但我们也希望了解延迟。因为队列中的项目有一个时间戳字段,表示它们被放入队列的时间,我的监控线程可以调用TryPeek
来获取队列头部的项目,从当前减去插入时间时间,并告诉我该项目在队列中的时间。随着时间的推移和许多样本,这让我非常清楚地了解了收到的物品需要多长时间。
当我的监控代码仍在检查时,其他一些线程可能会将项目出列并不重要。
我可以想到一些其他情况,在这些情况下,查看队列头部的内容会很有用,即使它可能会立即被取消。
答案 1 :(得分:1)
我有一个ConcurrentQueue
,其中许多主题可能Enqueue
,但我只限制TryPeek
和TryDequeue
之间的lock
和<{1}}的一个主题:
lock (dequeueLock)
if (queue.TryPeek(out item))
if (item.Value <= threshold)
queue.TryDequeue(out item);
注意:此代码运行时,其他线程可能会继续Enqueue
。
进行一些原子查看 - 检查 - 出列操作会更好,但lock
对我的情况来说很好。
答案 2 :(得分:0)
我的理解是,当您想要查看时使用此方法,但您不确定队列中是否有项目。通常,Peek在空队列中会抛出异常。如果项目不存在,TryPeek将返回false。这在多线程场景中非常有用,在这种情况下,另一个线程可能会在检查空队列和实际查看值之间将项目出列。
答案 3 :(得分:0)
TryPeek
用于等待对象位于队列的第一个位置。 TryDequeue
将使任何对象出列。因此,例如,我编写了一个多线程的Web服务器,但在授权期间,当为某个请求启用授权时,他们需要在一个点按照接收顺序进行处理。我不想锁定整个线程函数或它的一半,只是为了对某些客户端我可以按顺序处理它们的请求。
所以,我创建了一个Dictionary<string, ConcurrentQueue<HttpListenerContext>>
,然后在服务器线程的最开始,我暂时锁定并检查是否需要授权,如果是,我将HttpListenerContext
存储在队列中使用客户端IP作为字典键,以便不同的客户端不会不必要地阻塞彼此的线程。然后,我处理标头并正常计算哈希值,因为页面可能在初始化之后使用ajax和websockets连接发出两个或三个请求,最好多线程化授权信息的散列(这是我为HttpListener实现的摘要授权)我自己,所以我不限于使用Active Directory)。然后,当需要检查授权时,所谓的客户端现时计数仅比该客户端会话的最后一个请求(安全性功能)大一个,我使用我创建的que和TryPeek
{ {1}}要等到线程Thread.Yield()
是队列中第一个完成授权然后将其出列的队列。
简而言之,它可以用于多线程,对于大多数你希望并行运行的线程来说,利用不同的核心,但是对于它们中的一些线程,你需要一切都按顺序返回
答案 4 :(得分:0)
试试吧
T item = bc.GetConsumingEnumerable().FirstOrDefault();
if (item != null)
{
//...
}
答案 5 :(得分:0)