PFX ConcurrentQueue - 是有没有办法从队列中删除特定项目
-
22-08-2019 - |
题
我有具有有一个ID属性和每个项目的任务的ConcurrentQueue项的ConcurrentQueue一个应用程序,队列中的项目如下:
class QueueItem {
public int ID { get; set; }
public ConcurrentQueue<WorkItem> workItemQueue { get; set; }
}
和队列本身看起来像:
ConcurrentQueue<QueueItem> itemQueue;
我有一个线程正在执行在itemQueue一个foreach,从每个队列出队的项目并在其上做的工作:
foreach(var queueItem in itemQueue) {
WorkItem workItem;
if (queueItem.workItemQueue.TryDequeue(out workItem))
doWork(workItem);
else
// no more workItems for this queueItem
}
我使用ConcurrentQueues因为我有一个单独的线程潜在地添加queueItems到itemQueue,加入工作项到每个workItemQueue。
我的问题是当我有一个queueItem没有更多的工作项 - 我想删除queueItem从itemQueue - 类似...
if (queueItem.workItemQueue.TryDequeue(out workItem))
doWork(workItem);
else
itemQueue.TryRemove(queueItem);
...但我不能找到一个方法来做到这一点很容易。路上,我想出了是出列每个QueueItem,然后排队,如果有仍然在workItemQueue工作项:
for (int i = 0; i < itemQueue.Count; i++) {
QueueItem item;
itemQueue.TryDequeue(out queueItem);
if (queueItem.workItemQueue.TryDequeue(out workItem)) {
itemQueue.Enqueue(queueItem);
doWork(workItem);
}
else
break;
}
有没有更好的方式来完成我想用PFX ConcurrentQueue什么,或者这是做一个合理的方式,我应该使用自定义并发队列/列表实现还是我失去了一些东西?
解决方案
在一般情况下,就没有有效的方法来从队列中删除特定项目。他们一般有O(1)队列,出列,但为O(n)删除,这是您的实现做什么。
一种替代结构是一种叫做LinkedHashMap的。看一看在 Java实现如果你感兴趣。
它实质上是一个哈希表的和一个链表,它允许O(1)队列中,出列和删除。
这没有在净尚未实现,但也有几个实现浮动网路上。
现在,问题是,为什么itemQueue队列?从你的代码示例,你永远不排队或出队从东西它(除了导航围绕删除问题)。我有一个怀疑,如果使用更合适的数据结构中的问题可以简化。你能给上的代码访问什么其他部分的例子itemQueue?
其他提示
这可能不适合每一个人,但下面是我想出了从并发队列中删除一个项目的解决方案,因为这是第一个谷歌的结果,我想我会离开我的解决方案的背后。
我所做的是暂时用空代替工作队列,原转换成列表,删除的项目(S),然后创建一个从修改列表中的新队列,并把它放回去。
(抱歉这是VB.net而C#)在代码:
Dim found As Boolean = False
//'Steal the queue for a second, wrap the rest in a try-finally block to make sure we give it back
Dim theCommandQueue = Interlocked.Exchange(_commandQueue, New ConcurrentQueue(Of Command))
Try
Dim cmdList = theCommandQueue.ToList()
For Each item In cmdList
If item Is whateverYouAreLookingFor Then
cmdList.Remove(item)
found = True
End If
Next
//'If we found the item(s) we were looking for, create a new queue from the modified list.
If found Then
theCommandQueue = New ConcurrentQueue(Of Command)(cmdList)
End If
Finally
//'always put the queue back where we found it
Interlocked.Exchange(_commandQueue, theCommandQueue)
End Try
旁白:这是我的第一个答案,所以你自然可以将一些编辑的意见和/或修改我的答案
。当你要处理的FIFO风格的项目队列意味着,栈后进先出法。还有一个concurrentdictionary和concurrentbag。确保队列其实你想要的是。我不认为我会永远做一个foreach上concurrentqueue。
您可能想要的是你的工作项目单个队列(让他们使用共同的界面,使界面上的队列,接口应该公开继承类型,它可以在以后如果需要重铸)。如果工作项属于一个父,则属性可以用于将保持键与母体(考虑为密钥的GUID),和父可以保持在一个concurrentdictionary和参考/根据需要除去。
如果你必须这样做,你有它的方式,考虑增加一个标志。那么你可以标记在itemqueue的项目为“关闭”或什么的,这样,当它出列,它会被忽略。