Re: Синхронизация очереди
От: desco США http://v2matveev.blogspot.com
Дата: 03.05.07 14:53
Оценка:
Здравствуйте, DartVader, Вы писали:

можно сделать как-то так: (оригинальный вариант встретил, по-моему, в блоге Джо Даффи)
    abstract class Producer<T>
    {
        private readonly object _queueSyncRoot = new object();
        private readonly Queue<T> _queue = new Queue<T>();

        private volatile bool _finished;
        private Thread _thread;

        public void Start()
        {
            _finished = false;
            _thread = new Thread(Produce);
            _thread.Start();
        }

        public void Stop()
        {
            _finished = true;
            lock(_queueSyncRoot)
            {
                Monitor.PulseAll(_queueSyncRoot);
            }
        }

        public IEnumerable<T> Buffer
        {
            get
            {
                while(!_finished)
                {
                    T item;
                    lock(_queueSyncRoot)
                    {
                        if (_queue.Count == 0)
                        {
                            Monitor.Wait(_queueSyncRoot);
                        }
                        item = _queue.Dequeue();
                    }
                    yield return item;
                }
            }
        }

        protected abstract T Create();

        private void Produce()
        {
            while (!_finished)
            {
                T item = Create();
                lock(_queueSyncRoot)
                {
                    _queue.Enqueue(item);
                    Monitor.Pulse(_queueSyncRoot);
                }
            }
        }
    }

    abstract class Consumer<T>
    {
        private readonly Producer<T> _producer;
        private volatile bool _finished;
        private Thread _thread;

        protected Consumer(Producer<T> _producer)
        {
            this._producer = _producer;
        }

        public void Start()
        {
            _finished = false;
            _thread = new Thread(Consume);
            _thread.Start();
        }

        public void Stop()
        {
            _finished = true;
        }

        protected abstract void Consume(T item);

        private void Consume()
        {
            foreach (T obj in _producer.Buffer)
            {
                Consume(obj);
                if (_finished)
                {
                    break;
                }
            }
        }
    }

   class NumberProducer : Producer<int>
    {
        private int _i;
        protected override int Create()
        {
            return ++_i;
        }
    }

    class NumberConsumer : Consumer<int>
    {
        public NumberConsumer(Producer<int> producer) 
            : base(producer)
        {
        }

        protected override void Consume(int item)
        {
            Console.WriteLine(item);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            NumberProducer p = new NumberProducer();
            NumberConsumer c1 = new NumberConsumer(p);
            NumberConsumer c2 = new NumberConsumer(p);
            NumberConsumer c3 = new NumberConsumer(p);

            p.Start();
            c1.Start();c2.Start();c3.Start();

            Console.ReadKey();

            c1.Stop();c2.Stop();c3.Stop();
            p.Stop();
        }
    }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.