나는 다음 클래스처럼 그것을 할 것입니다. 대기열 중 하나에 항목을 추가 할 때 Enqueue()
으로 전화하면됩니다. 이 메서드는 항상 (거의) 즉시 반환합니다. 다른 스레드에서는 항목을 소비 할 준비가되었을 때 Dequeue()
으로 전화를 겁니다. 우선 순위가 높은 대기열에서 먼저 가져옵니다. 현재 대기열에서 항목을 사용할 수없는 경우 호출이 차단됩니다. 생산이 끝나면 Complete()
으로 전화하십시오. 호출이 이루어지고 두 대기열이 모두 비어지면 Dequeue()
으로의 다음 호출 (또는 현재 차단 된 호출)은 InvalidOperationException
을 던집니다.
생산자가 소비자보다 오랜 기간 동안 빠를 수 있다면 대기열 (new BlockingCollection<T>(capacity)
)을 묶어야합니다. 그러나이 경우 낮은 우선 순위 항목과 높은 우선 순위 항목을 모두 생성하는 스레드가 하나만있는 경우 우선 순위가 높은 항목은 우선 순위가 낮은 항목을 기다려야 할 수 있습니다. 우선 순위가 높은 항목을 생성하는 스레드와 우선 순위가 낮은 항목을 생성하는 스레드가 하나씩있어 문제를 해결할 수 있습니다. 또는 우선 순위가 높은 대기열 만 바인딩하면 한 번에 100 만 개의 우선 순위가 낮은 항목을 얻을 수 없기를 바랍니다.
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();
}
}
대단히 감사합니다. 나는 정보와 제안에 정말로 감사한다! – user685869