简体   繁体   English

为什么我正在等待QWaitCondition的线程没有返回

[英]Why is my thread which is waiting on a QWaitCondition not returning

I have data structure where I want to wait until it recives data. 我有数据结构,我想等到它重新获取数据。 When I call setInterrupt I want my thread to stop but it never returns. 当我调用setInterrupt时,我希望我的线程停止但它永远不会返回。

This is my queue: 这是我的队列:

  BufferedIpQqueue::BufferedIpQqueue()
    {

    }

    BufferedIpQqueue::~BufferedIpQqueue()
    {
        bufferWaitCondition.wakeAll();
    }

    QString BufferedIpQqueue::get()
    {
        QMutexLocker locker(&mutex);

        while(queue.isEmpty())
        {
            qDebug() << "waiting at mutex " << &mutex << "calling threadid: " << QThread::currentThreadId();
            bufferWaitCondition.wait(&mutex);
        }

        return queue.first();
    }

void BufferedIpQqueue::put(QString &data)
{
    QMutexLocker locker(&mutex);

    queue.append(data);
    bufferWaitCondition.wakeAll();
}

void BufferedIpQqueue::wakAllThreads()
{
    qDebug() << "wake all waiting threads at mutex: " <<  &mutex << "calling threadid: " << QThread::currentThreadId();
    bufferWaitCondition.wakeAll();
}

This is my consumer thread: 这是我的消费者主题:

IpCheckWorker::IpCheckWorker(BufferedIpQqueue *queue)
{
    this->queue = queue;

    interrupt = false;
}

void IpCheckWorker::setInterrupt(bool value)
{
    QMutexLocker lock(&mutex);
    qDebug() << "wake all threads";
    interrupt = value;
    queue->wakAllThreads();
}

bool IpCheckWorker::getInterruptFlag()
{
    QMutexLocker lock(&mutex);

    return interrupt;
}


void IpCheckWorker::process()
{
    while(getInterruptFlag() == false)
    {

        qDebug() << "enter process loop ThreadID:" << QThread::currentThreadId();
        QString check_ip = queue->get();

        qDebug() << "proccess ThreadID:" << QThread::currentThreadId();
    }
    qDebug() << "leave process event ThreadID:" << QThread::currentThreadId();
    emit finished();

}

I get the following output: 我得到以下输出:

  • enter process loop ThreadID: 0xf94 进入进程循环ThreadID:0xf94
  • waiting at mutex 0x51ab5f0 calling threadid: 0xf94 在mutex 0x51ab5f0等待调用threadid:0xf94
  • wake all threads 唤醒所有线程
  • wake all waiting threads at mutex: 0x51ab5f0 calling threadid: 0x10dc 唤醒所有等待线程在互斥锁:0x51ab5f0调用threadid:0x10dc
  • waiting at mutex 0x51ab5f0 calling threadid: 0xf94 在mutex 0x51ab5f0等待调用threadid:0xf94

It seems like I am stock at while(queue.isEmpty()) in my BufferedIpQqueue::get() method. 好像我在BufferedIpQqueue :: get()方法中的while(queue.isEmpty())库存。 Why is my mthod not returning to IpCheckWorker::process()? 为什么我的方法没有返回到IpCheckWorker :: process()?

Any help how to do it right would be very kind. 如何正确地做任何帮助都会非常友好。

What you are doing is reimplementing a slightly less flexible QThreadPool . 你正在做的是重新实现一个稍微不那么灵活的QThreadPool If you wish, you can look in its implementation for how it uses the wait conditions. 如果您愿意,可以查看其实现方式 ,了解它如何使用等待条件。 I'd simply advise to use QThreadPool and call it a day, since it's a perfect fit for your requirements. 我只是建议使用QThreadPool并将其称为一天,因为它非常适合您的要求。

The thread pool maintains a queue of QRunnable instances. 线程池维护QRunnable实例的队列。 The instances are picked up by idle threads. 实例由空闲线程拾取。 The thread management is automatic. 线程管理是自动的。 QRunnable is a lightweight class similar to QEvent - it is not a QObject . QRunnable是一个类似于QEvent的轻量级类 - 它不是QObject

QThreadPool is not a singleton. QThreadPool 不是单身人士。 There is a global instance, but you don't have to use it. 有一个全局实例,但您不必使用它。 You can have your own instance. 您可以拥有自己的实例。

This example is compatible with Qt 4.4 & up. 此示例与Qt 4.4及更高版本兼容。

#include <QCoreApplication>
#include <QThreadPool>
#include <QRunnable>
#include <QBasicTimer>
#include <QDebug>
#include <cstdlib>

class Thread : public QThread {
public:
  using QThread::msleep;
};

class IpData {
  QString m_value;
public:
  IpData(const QString & str) : m_value(str) {}
  const QString & value() const { return m_value; }
};

class IpRunnable : public QRunnable, IpData {
  void run() {
    qDebug() << "[" << QThread::currentThreadId()
             << "] processing ip" << value();
    Thread::msleep(qrand() < (RAND_MAX/4.0) ? 0 : 100);
  }
public:
  IpRunnable(const IpData & data) : IpData(data) {}
  IpRunnable(const QString & str) : IpData(str) {}
};

class Test : public QObject {
  Q_OBJECT
  int i;
  QBasicTimer timer;
  void timerEvent(QTimerEvent * t) {
    if (t->timerId() != timer.timerId()) return;
    QThreadPool::globalInstance()->start(new IpRunnable(QString::number(i)));
    if (++i > 100) qApp->quit();
  }
public:
  Test() : i(0) { timer.start(20, this); }
};

int main(int argc, char *argv[])
{
  QCoreApplication app(argc, argv);
  QThreadPool::globalInstance()->setMaxThreadCount(5);
  Test test;
  return app.exec();
}

#include "main.moc"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM