我有一个像这样运行生产者-消费者模型的类:
public class SyncEvents
{
public bool waiting;
public SyncEvents()
{
waiting = true;
}
}
public class Producer
{
private readonly Queue<Delegate> _queue;
private SyncEvents _sync;
private Object _waitAck;
public Producer(Queue<Delegate> q, SyncEvents sync, Object obj)
{
_queue = q;
_sync = sync;
_waitAck = obj;
}
public void ThreadRun()
{
lock (_sync)
{
while (true)
{
Monitor.Wait(_sync, 0);
if (_queue.Count > 0)
{
_sync.waiting = false;
}
else
{
_sync.waiting = true;
lock (_waitAck)
{
Monitor.Pulse(_waitAck);
}
}
Monitor.Pulse(_sync);
}
}
}
}
public class Consumer
{
private readonly Queue<Delegate> _queue;
private SyncEvents _sync;
private int count = 0;
public Consumer(Queue<Delegate> q, SyncEvents sync)
{
_queue = q;
_sync = sync;
}
public void ThreadRun()
{
lock (_sync)
{
while (true)
{
while (_queue.Count == 0)
{
Monitor.Wait(_sync);
}
Delegate query = _queue.Dequeue();
query.DynamicInvoke(null);
count++;
Monitor.Pulse(_sync);
}
}
}
}
/// <summary>
/// Act as a consumer to the queries produced by the DataGridViewCustomCell
/// </summary>
public class QueryThread
{
private SyncEvents _syncEvents = new SyncEvents();
private Object waitAck = new Object();
private Queue<Delegate> _queryQueue = new Queue<Delegate>();
Producer queryProducer;
Consumer queryConsumer;
public QueryThread()
{
queryProducer = new Producer(_queryQueue, _syncEvents, waitAck);
queryConsumer = new Consumer(_queryQueue, _syncEvents);
Thread producerThread = new Thread(queryProducer.ThreadRun);
Thread consumerThread = new Thread(queryConsumer.ThreadRun);
producerThread.IsBackground = true;
consumerThread.IsBackground = true;
producerThread.Start();
consumerThread.Start();
}
public bool isQueueEmpty()
{
return _syncEvents.waiting;
}
public void wait()
{
lock (waitAck)
{
while (_queryQueue.Count > 0)
{
Monitor.Wait(waitAck);
}
}
}
public void Enqueue(Delegate item)
{
_queryQueue.Enqueue(item);
}
}
代码运行流畅,但 wait() 函数。 在某些情况下,我想等到队列中的所有函数都运行完毕,所以我创建了 wait() 函数。
生产者将在合适的时间触发 waitAck 脉冲。
但是,当行“Monitor.Wait(waitAck);”在wait()函数中运行,所有线程停止,包括生产者和消费者线程。
为什么会发生这种情况,我该如何解决?谢谢!
最佳答案
所有线程实际上都停止似乎不太可能,但我应该指出,为避免错误唤醒,您可能应该使用 while 循环而不是 if 语句:
lock (waitAck)
{
while(queryProducer.secondQueue.Count > 0)
{
Monitor.Wait(waitAck);
}
}
您正在调用 Monitor.Wait
的事实意味着 waitAck
应该被释放,因此它不应该阻止消费者线程锁定...
您能否提供有关生产者/消费者线程“停止”方式的更多信息?看起来他们刚刚陷入僵局?
您的制作人使用的是 Notify
还是 NotifyAll
?你现在有一个额外的等待线程,所以如果你只使用 Notify
它只会释放一个线程......如果没有你的 Producer
和 Consumer
类。
如果您能展示一个简短但完整的程序来演示问题,那将会有所帮助。
编辑:好的,现在您已经发布了代码,我可以看到一些问题:
拥有如此多的公共(public)变量是灾难的根源。您的类应该封装它们的功能,这样其他代码就不必四处寻找实现的点点滴滴。 (例如,您在此处的调用代码实际上不应该访问队列。)
您将项目直接添加到第二个队列,这意味着您无法有效地唤醒生产者以将它们添加到第一个队列。为什么你甚至有多个队列?
您总是在生产者线程中等待
_sync
...为什么?什么会通知它开始?一般来说,生产者线程不必等待,除非你有一个有界缓冲区您有一个静态 变量 (_waitAck),每次您创建一个新实例时它都会被覆盖。这是个坏主意。
您还没有显示您的 SyncEvents
类 - 这意味着要做什么有趣的事情吗?
老实说,您的设计似乎很奇怪 - 您最好从头开始。尝试将整个生产者/消费者队列封装在一个类中,该类具有 Produce
和 Consume
方法,以及 WaitForEmpty
(或类似的东西那)。我想您会发现这样同步逻辑会容易得多。
关于C# 一旦主线程休眠,所有线程停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2294485/