Здравствуйте, 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();
}
}