简体   繁体   中英

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.

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
  • waiting at mutex 0x51ab5f0 calling threadid: 0xf94
  • wake all threads
  • wake all waiting threads at mutex: 0x51ab5f0 calling threadid: 0x10dc
  • waiting at mutex 0x51ab5f0 calling threadid: 0xf94

It seems like I am stock at while(queue.isEmpty()) in my BufferedIpQqueue::get() method. Why is my mthod not returning to IpCheckWorker::process()?

Any help how to do it right would be very kind.

What you are doing is reimplementing a slightly less flexible 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.

The thread pool maintains a queue of QRunnable instances. 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 .

QThreadPool is not a singleton. 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.

#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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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