我有具有有一个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的项目为“关闭”或什么的,这样,当它出列,它会被忽略。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top