C#一旦主线程休眠,所有线程都停止了

我有一个运行Producer-Consumer模型的类,如下所示:

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类的细节,很难看出这是否是一个问题.

如果您可以展示一个简短但完整的程序来演示问题,那将有所帮助.

编辑:好的,现在你已经发布了我可以看到许多问题的代码:

>拥有如此多的公共变量是一种灾难.你的类应该封装它们的功能,这样其他代码就不必去寻找实现的部分. (例如,您的调用代码实际上不应该访问队列.)
>您将项目直接添加到第二个队列,这意味着您无法有效唤醒生产者将其添加到第一个队列.为什么你甚至有多个队列?
>你总是在生产者线程中等待_sync …为什么?什么会开始通知它?一般来说,生产者线程不应该等待,除非你有一个有界缓冲区
>您有一个静态变量(_waitAck),每次创建新实例时都会被覆盖.这是个坏主意.

你还没有展示你的SyncEvents类 – 这是否意味着做任何有趣的事情?

说实话,你似乎有一个很奇怪的设计 – 你可能最好从头开始.尝试将整个生产者/消费者队列封装在一个类中,该类具有Produce和Consume方法,以及WaitForEmpty(或类似的东西).我认为你会发现同步逻辑更容易.

点赞