我会像下面的课程那样做。Enqueue()
当您生产一个项目以将其添加到其中一个队列时,您调用它。此方法总是(几乎)立即返回。在另一个线程中,您Dequeue()
在准备好使用某个项目时调用。它尝试首先从高优先级队列中获取。如果此时任何队列中都没有可用的项目,则调用阻塞。完成制作后,调用Complete()
. 在进行该调用并且两个队列都为空之后,下一次调用(或当前阻塞的调用)Dequeue()
throws InvalidOperationException
。
如果您的生产者可以在很长一段时间内比您的消费者更快,您应该绑定队列(new BlockingCollection<T>(capacity)
)。但在这种情况下,如果您只有一个线程同时产生低优先级和高优先级项目,则高优先级项目可能不得不等待低优先级项目。您可以通过让一个线程用于生成高优先级项目和一个用于低优先级项目的线程来解决此问题。或者您可以只绑定高优先级队列,并希望您不会一次获得一百万个低优先级项目。
class Worker<T>
{
BlockingCollection<T> m_highPriorityQueue = new BlockingCollection<T>();
BlockingCollection<T> m_lowPriorityQueue = new BlockingCollection<T>();
public void Enqueue(T item, bool highPriority)
{
BlockingCollection<T> queue;
if (highPriority)
queue = m_highPriorityQueue;
else
queue = m_lowPriorityQueue;
queue.Add(item);
}
public T Dequeue()
{
T result;
if (!m_highPriorityQueue.IsCompleted)
{
if (m_highPriorityQueue.TryTake(out result))
return result;
}
if (!m_lowPriorityQueue.IsCompleted)
{
if (m_lowPriorityQueue.TryTake(out result))
return result;
}
if (m_highPriorityQueue.IsCompleted && m_lowPriorityQueue.IsCompleted)
throw new InvalidOperationException("All work is done.");
else
{
try
{
BlockingCollection<T>.TakeFromAny(
new[] { m_highPriorityQueue, m_lowPriorityQueue },
out result);
}
catch (ArgumentException ex)
{
throw new InvalidOperationException("All work is done.", ex);
}
return result;
}
}
public void Complete()
{
m_highPriorityQueue.CompleteAdding();
m_lowPriorityQueue.CompleteAdding();
}
}