BlockingCollection<> 中的元素顺序
我有一个使用 BlockingCollection<>
实现的下载队列。现在我想偶尔优先进行一些下载。我认为将一些元素“向上”移动到集合中可能很棒,就像在列表中一样,但是没有像Remove()/AddFirst()或Move()这样的方法。
在 BlockingCollection<>
中排列项目的首选方式是什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不幸的是,无法按照您想要的方式重新排列队列。您真正需要的是一个作为优先级队列实现的
PriorityBlockingCollection
,但遗憾的是,它也不存在。您可以做的是利用
TakeFromAny
方法来获取您想要的优先级行为。TakeFromAny
将从BlockingCollection
实例数组中取出第一个可用项目。它将优先考虑数组中首先列出的队列。上面的示例将打印:
它强制您使用多个队列,因此它不是最优雅的解决方案。
Unfortunately there is no way to rearrange the queue in the manner you desire. What you really need is a
PriorityBlockingCollection
implemented as a priority queue, but alas that does not exist either.What you can do is exploit the
TakeFromAny
method to get the priority behavior you want.TakeFromAny
will dequeue the first available item from an array ofBlockingCollection
instances. It will give priority to queues listed first in the array.The example above will print:
It forces you to use to multiple queues so it is not the most elegant solution.
BlockingCollection
通过包装内部来工作IProducerConsumerCollection
。默认情况下在内部使用ConcurrentQueue
,但您可以通过 此构造函数。如果您提供自己的线程安全集合,则可以使用您想要的任何集合类型。这将允许您根据需要对元素进行优先级排序。
虽然没有内置集合可以实现您所需的功能,但您可以将一对
ConcurrentQueue
集合包装到实现IProducerConsumerCollection
的类中。这将允许您拥有“高优先级”和“低优先级”元素。BlockingCollection<T>
works by wrapping an internalIProducerConsumerCollection<T>
. The default is to use aConcurrentQueue<T>
internally, but you can provide your own implementation via this constructor.If you provide your own threadsafe collection, you can use any collection type you want. This would allow to you prioritize elements as needed.
While there are no built-in collections that will implement your desired functionality, you could probably wrap a pair of
ConcurrentQueue<T>
collections into a class that implementsIProducerConsumerCollection<T>
. This would allow you to have "high priority" and "low priority" elements.无法直接在
BlockingCollection
之上实现优先级队列。最好将BlockingCollection
视为无法实现重新排序的严格队列。不过,您可以结合使用优先级队列和
BlockingCollection
来实现相同的效果。让我们假设您实现了一个简单的PriorityQueue
,它可以正确排序您的下载。以下内容可用于为接收方的处理添加优先级。 注意:PriorityQueue 不是 .Net Framework 中实际存在的类型。您需要根据下载项目的优先级安排自己编写它。
There is no way to implement a priority queue directly on top of a
BlockingCollection<T>
. ABlockingCollection<T>
is best viewed as a strict queue for which no reordering can be achieved.However you could use a combination of a priority queue and a
BlockingCollection<T>
to achieve the same effect. Lets assume for a second you implemented a simplePriorityQueue<T>
which correctly orders your downloads. The following could be used to add priority to the handling of the receiving sideNote:
PriorityQueue<T>
is not a type that actually exists in the .Net Framework. It's something you'd need to write yourself based on the priority scheduling of downloaded items.Reed 正确地告诉您需要实现
IProducerConsumerCollection
。但是,有一门课程可以帮助您。它不是内置的,但它在 上有特色MSDN。只需将此ConcurrentPriorityQueue
传递到您的BlockingCollection
即可。这就是我使用它的方式:
ICommand
是我项目中的一个接口。现在,您可以添加如下项目:
优先级较低的整数值的项目将首先执行。在上面的示例中:
当循环
BlockingCollection
时,您将不再获得单个元素(在我的例子中是ICommand
),而是一个KeyValuePair
。当然,这可能需要更改一些代码。一件好事是你有其最初的优先级:Reed is correct in telling you that you need to implement the
IProducerConsumerCollection<T>
. However, there is a class that can help you. It's not built in, but it's featured on MSDN. Just pass thisConcurrentPriorityQueue
to yourBlockingCollection
.This is how I used it:
The
ICommand
is an interface in my project.Now this allows you to add items like this:
Items with a lower integer value as priority will be executed first. In the above example:
When looping over your
BlockingCollection
, you will no longer get the single elements (ICommand
in my case), but aKeyValuePair
. This might require some code changes of course. A nice thing is that you have its original priority: