Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当许多产品_C#_Design Patterns_Events_.net 3.5 - Fatal编程技术网

C# 当许多产品

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

我有一个生产者-消费者模式为一种产品工作。当生产商生产许多产品时,什么是最佳实施方案?例如,使用者应使用的DataBaseEvent、GuiEvent和ControlEvent。下面的代码显示了DataBaseEvent中一个产品的模式。每个事件类型是否应在自己的队列中排队,或者事件是否继承可以排队的基类。在处理许多事件类型时,可能存在更好的模式

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。