C# 具有资源的生产者-消费者
我试图用一组资源实现生产者/消费者模式,因此每个线程都有一个与其关联的资源。例如,我可能有一个任务队列,其中每个任务都需要一个C# 具有资源的生产者-消费者,c#,multithreading,producer-consumer,C#,Multithreading,Producer Consumer,我试图用一组资源实现生产者/消费者模式,因此每个线程都有一个与其关联的资源。例如,我可能有一个任务队列,其中每个任务都需要一个StreamWriter来写入其结果。每个任务还必须向其传递参数 我从Joseph Albahari的实现开始(我的修改版本见下文) 我将Action队列替换为Action队列,其中T是资源,并将与线程关联的资源传递给Action。但是,这就给我留下了如何将参数传递给操作的问题。显然,操作必须替换为委托,但这留下了任务排队时如何传递参数的问题(从ProducerConsu
StreamWriter
来写入其结果。每个任务还必须向其传递参数
我从Joseph Albahari的实现开始(我的修改版本见下文)
我将Action
队列替换为Action
队列,其中T
是资源,并将与线程关联的资源传递给Action
。但是,这就给我留下了如何将参数传递给操作
的问题。显然,操作
必须替换为委托,但这留下了任务排队时如何传递参数的问题(从ProducerConsumerQueue
类外部)。有什么办法吗
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.
}
}
}
类ProducerConsumerQueue
{
只读对象_locker=新对象();
线程【】u工人;
队列_itemQ=新队列();
公共ProducerConsumerQueue(T[]资源)
{
_workers=新线程[resources.Length];
//为每个工作线程创建并启动一个单独的线程
for(int i=0;i消耗(资源[i]);
SetApartmentState(ApartmentState.STA);
_工人[i]=线程;
_workers[i].Start();
}
}
公共无效关闭(bool waitForWorkers)
{
//为每个工作人员排队一个空项以进行每个退出。
foreach(线程工作线程)
排队项目(空);
//等待工人完成
if(等待工人)
foreach(线程工作线程)
worker.Join();
}
公共无效排队项(操作项)
{
锁(储物柜)
{
_itemQ.Enqueue(item);//我们必须脉冲,因为我们
Monitor.Pulse(_locker);//更改阻塞条件。
}
}
无效消耗(T参数)
{
while(true)//继续消费直到
{//我不是这么说的。
行动项目;
锁(储物柜)
{
while(_itemQ.Count==0)Monitor.Wait(_locker);
item=_itemQ.Dequeue();
}
if(item==null)return;//这表示我们退出。
项(参数);//执行项。
}
}
}
ProducerConsumerQueue
中的类型T
不一定是您的资源,它可以是包含您的资源的复合类型。使用.NET4最简单的方法是使用Tuple
。product/consumer队列只吃并吐出T
,因此在操作中,您可以使用属性获取资源和参数。如果您使用的是Tuple
,您将使用Item1
获取资源,使用Item2
获取参数
如果不使用.NET4,则过程类似,但您只需创建自己的类:
public class WorkItem<T>
{
private StreamWriter resource;
private T parameter;
public WorkItem(StreamWriter resource, T parameter)
{
this.resource = resource;
this.parameter = parameter;
}
public StreamWriter Resource { get { return resource; } }
public T Parameter { get { return parameter; } }
}
现在我们可以使用这样的类:
var processor = new Processor();
for (int i = 0; i < 10; i++)
processor.Process(i);
var处理器=新处理器();
对于(int i=0;i<10;i++)
处理程序(i);
同时计划的任务不会超过三个,每个任务都有自己的StreamWriter
资源可回收。问题是我不想为每个任务提供自己的StreamWriter。我希望每个StreamWriter都属于一个线程,该线程在执行任务时将重用它。
var processor = new Processor();
for (int i = 0; i < 10; i++)
processor.Process(i);