나는 리소스마다 프로듀서/소비자 패턴을 구현하려고합니다. 따라서 각 스레드는 관련된 하나의 리소스를 갖습니다. 예를 들어, 각 작업에서 결과를 쓸 때 StreamWriter
이 필요한 작업 대기열이있을 수 있습니다. 각 작업에는 매개 변수가 전달되어야합니다.생산자 - 리소스가있는 소비자
조셉 알바하리 (Joseph Albahari)의 구현으로 시작했습니다 (제 수정 된 버전은 아래 참조).
난T
자원이다
Action<T>
의
Action
큐의 큐를 대체하고,
Action
의 스레드와 관련된 리소스를 전달한다. 그러나 이것으로 인해 매개 변수를
Action
에 전달하는 방법의 문제가 생깁니다. 분명히
Action
은 대리자로 바꿔야하지만 이는 작업이 대기열에 들어갈 때 (
ProducerConsumerQueue
클래스 외부에서) 매개 변수를 전달하는 방법의 문제를 남깁니다. 이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
ProducerConsumerQueue<T>
에서
class ProducerConsumerQueue<T>
{
readonly object _locker = new object();
Thread[] _workers;
Queue<Action<T>> _itemQ = new Queue<Action<T>>();
public ProducerConsumerQueue(T[] resources)
{
_workers = new Thread[resources.Length];
// Create and start a separate thread for each worker
for (int i = 0; i < resources.Length; i++)
{
Thread thread = new Thread(() => Consume(resources[i]));
thread.SetApartmentState(ApartmentState.STA);
_workers[i] = thread;
_workers[i].Start();
}
}
public void Shutdown(bool waitForWorkers)
{
// Enqueue one null item per worker to make each exit.
foreach (Thread worker in _workers)
EnqueueItem(null);
// Wait for workers to finish
if (waitForWorkers)
foreach (Thread worker in _workers)
worker.Join();
}
public void EnqueueItem(Action<T> item)
{
lock (_locker)
{
_itemQ.Enqueue(item); // We must pulse because we're
Monitor.Pulse(_locker); // changing a blocking condition.
}
}
void Consume(T parameter)
{
while (true) // Keep consuming until
{ // told otherwise.
Action<T> item;
lock (_locker)
{
while (_itemQ.Count == 0) Monitor.Wait(_locker);
item = _itemQ.Dequeue();
}
if (item == null) return; // This signals our exit.
item(parameter); // Execute item.
}
}
}
문제는 각 작업에 자체 StreamWriter를 제공하고 싶지 않다는 것입니다.각 StreamWriter가 작업을 실행할 때 다시 사용할 스레드에 속하기를 원합니다. – Johnny