C# 当许多产品
我有一个生产者-消费者模式为一种产品工作。当生产商生产许多产品时,什么是最佳实施方案?例如,使用者应使用的DataBaseEvent、GuiEvent和ControlEvent。下面的代码显示了DataBaseEvent中一个产品的模式。每个事件类型是否应在自己的队列中排队,或者事件是否继承可以排队的基类。在处理许多事件类型时,可能存在更好的模式C# 当许多产品,c#,design-patterns,events,.net-3.5,C#,Design Patterns,Events,.net 3.5,我有一个生产者-消费者模式为一种产品工作。当生产商生产许多产品时,什么是最佳实施方案?例如,使用者应使用的DataBaseEvent、GuiEvent和ControlEvent。下面的代码显示了DataBaseEvent中一个产品的模式。每个事件类型是否应在自己的队列中排队,或者事件是否继承可以排队的基类。在处理许多事件类型时,可能存在更好的模式 class DataBaseEventArgs : EventArgs { public string textToDB = ""; } c
class DataBaseEventArgs : EventArgs
{
public string textToDB = "";
}
class Consumer
{
private Producer mProducer = new Producer();
private Queue<DataBaseEventArgs> mDataBaseEventQueue = new Queue<DataBaseEventArgs>();
private static EventWaitHandle mDataBaseEventWaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private Thread mDataBaseEventDequeueThread = null;
public Consumer()
{
mDataBaseEventDequeueThread = new Thread(DataBaseDequeueEvent);
mDataBaseEventDequeueThread.Start();
mProducer.mDataBaseEventHandler += WhenDataBaseEvent;
}
protected void DataBaseDequeueEvent()
{
while (true)
{
DataBaseEventArgs e;
lock (((ICollection)mDataBaseEventQueue).SyncRoot)
{
if (mDataBaseEventQueue.Count > 0)
{
e = mDataBaseEventQueue.Dequeue();
}
}
// WriteToDatabase(e.textToDB);
if (mDataBaseEventQueue.Count == 0)
{
mDataBaseEventWaitHandle.WaitOne(1000);
mDataBaseEventWaitHandle.Reset();
}
}
}
internal void WhenDataBaseEvent(object sender, DataBaseEventArgs e)
{
lock (((ICollection)mDataBaseEventQueue).SyncRoot)
{
mDataBaseEventQueue.Enqueue(e);
mDataBaseEventWaitHandle.Set();
}
}
}
class Producer
{
public event EventHandler<DataBaseEventArgs> mDataBaseEventHandler = null;
public void SendDataBaseEvent()
{
if (mDataBaseEventHandler != null)
{
DataBaseEventArgs e = new DataBaseEventArgs();
e.textToDB = "This text will be written to DB";
mDataBaseEventHandler(this, e);
}
}
}
我认为,如果所有请求具有相同的优先级,并且将以类似的方式处理,那么最好将所有请求排队到一个队列中 如果其中一个请求具有更高的概率,那么要么需要一些奇特的优先级队列,要么可以使用不同的队列
此外,如果您以不同的方式处理消息,则没有必要使模式过于复杂。如果您希望主动分离工作,多个队列将非常有用-即,对于不同类型的事件,有不同的线程/池。如果您想共享负载,还有另一个选项-使用接口而不是基类。基类很好,但我想不出有什么东西可以在接口上强制使用基类。甚至只是一个工作的代表 另外-我不确定在这种情况下是否需要重置事件;通常,您可以只使用lock和Monitor.Pulse/Wait来处理生产者/消费者,这会减少开销,因为不涉及操作系统对象,只涉及托管对象。然而,如果代码当前是稳定的,那么可能保持原样-线程很难正确执行一次,更不用说两次了 但作为参考,它可能类似于:
while(true) {
T item;
lock(lockObj) {
if(queue.Count == 0) { // empty
Monitor.Wait(lockObj);
continue; // ensure there is genuinely something to do
}
item = queue.Dequeue();
}
// TODO: process item
}
...
void Add(T item) {
lock(lockObj) {
queue.Enqueue(item);
if(queue.Count == 1) { // first
Monitor.PulseAll(lockObj);
}
}
}
在清除队列时,请记住pulsell感谢您提供的监控代码示例。我想我将使用它而不是EventWaitHandler。