Mat*_*ite 12 .net queue collections concurrency multithreading
我有一个下载队列实现BlockingCollection<>.现在我想暂时优先考虑一些下载.我认为将一些元素"向上"移动可能会很棒,就像在列表中一样,但是没有像Remove()/ AddFirst()或Move()这样的方法.
安排物品的首选方式是BlockingCollection<>什么?
Bri*_*eon 17
不幸的是,没有办法以你想要的方式重新排列队列.你真正需要的是PriorityBlockingCollection作为优先级队列实现,但也不存在.
您可以做的是利用该TakeFromAny方法获得所需的优先级行为.TakeFromAny将从一组BlockingCollection实例中出列第一个可用项.它将优先考虑数组中首先列出的队列.
var low = new BlockingCollection<object> { "low1", "low2" };
var high = new BlockingCollection<object> { "high1", "high2" };
var array = new BlockingCollection<object>[] { high, low };
while (true)
{
object item;
int index = BlockingCollection<object>.TakeFromAny(array, out item);
Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)
上面的例子将打印:
high1
high2
low1
low2
Run Code Online (Sandbox Code Playgroud)
它会强制您使用多个队列,因此它不是最优雅的解决方案.
BlockingCollection<T>通过包装内部工作IProducerConsumerCollection<T>.默认是在ConcurrentQueue<T>内部使用,但您可以通过此构造函数提供自己的实现.
如果您提供自己的线程安全集合,则可以使用所需的任何集合类型.这将允许您根据需要确定元素的优先级.
虽然没有可以实现所需功能的内置集合,但您可以将一对ConcurrentQueue<T>集合包装到实现的类中IProducerConsumerCollection<T>.这将允许您具有"高优先级"和"低优先级"元素.
无法直接在a之上实现优先级队列BlockingCollection<T>.A BlockingCollection<T>最好被视为严格的队列,不能实现重新排序.
但是,您可以使用优先级队列和a的组合BlockingCollection<T>来实现相同的效果.让我们假设您实现了一个简单的PriorityQueue<T>正确下载您的下载.以下内容可用于为接收方的处理添加优先级
class DownloadManager {
private PriorityQueue<Download> m_priorityQueue;
private BlockingCollection<Download> m_downloadCollection;
public bool TryGetNext(ref Download download) {
PumpDownloadCollection();
if (m_priorityQueue.IsEmpty) {
download = null;
return false;
}
download = m_priorityQueue.Dequeue();
return true;
}
private void PumpDownloadCollection() {
T value;
while (m_downloadCollection.TryTake(out value)) {
m_priorityQueue.Enqueue(value);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:PriorityQueue<T>不是.Net Framework中实际存在的类型.根据下载项目的优先级安排,您需要自己编写.