0

我想为生产者/消费者情况实现基于循环的调度,其中消费者可能在运行时发生变化。

一开始我用了一个Queue包含所有消费者的 a ,将一个出队并立即再次将其入队以进行循环集合,效果很好。每当有新的消费者注册时,我都会将其排入队列 -> 完成。

然而,在运行时(当他们发送取消订阅消息时)移除消费者的问题是具有挑战性的。队列不提供 Remove() 方法,但是,我需要将它们完全从队列中删除 - 与消费者在队列中的当前位置无关。显然,Queue界面”并不是我所需要的。

C# 中是否有某种我没听说过的“循环集合”?

4

2 回答 2

2

从队列中间删除东西是一团糟:你最终会迭代所有项目,并且只重新排队那些你不想删除的项目。像这样的东西可能会起作用:

int count = q.Count;
for (int i = 0 ; i != count ; i++) {
    var item = q.Dequeue();
    if (!toRemove.Equals(item)) {
        q.Enqueue(item);
    }
}

但是,这需要遍历整个队列,所以它是O(n). 更好的方法可能是保留HashSet<T> toRemove已删除的项目,并以这样的方式包装 dequeue 方法,即删除项目需要快速toRemove.Add(removedItem),除实际排队外,入队需要删除itemfrom toRemove,而出队需要对项目进行额外检查存在于toRemove.

当然,您始终可以实现自己的循环缓冲区,这可以让您从中间删除项目,只需将缓冲区返回到前面,将您希望保留的项目复制到自身,并在您需要时调整“头”指针完毕。

于 2013-09-08T16:41:53.660 回答
0

在阅读了 dasblinkenlight 的答案后,我现在正在使用LinkedList基于 - 的方法。

  • AddConsumer -> linkedList.AddLast
  • RemoveConsumer -> linkedList.Remove
  • 获取下一个消费者

    var next = linkedList.First.Value; 链接列表.RemoveFirst(); 链接列表.AddLast(下一个); 下一个返回;

这可以解决问题,RemoveConsumer 是 O(N),但是,这还不错,因为 remove 很少发生。

于 2013-09-08T16:54:06.123 回答