QThread::sleep убивает поток в Qt

Хотел написать простенькое приложение с использоваанием QWaitCondition. Возникла проблема при работе потоков ActionThread, а именно при засыпании потока с помощью метода QThread::sleep(100) поток ббольше не просыпается и не доходит до строчки qDebug() << "I slept"! Если убрать метод sleep(), то всё будет работать нормально. Подскажите, в чём загвоздка? Ниже приведён код программы.

Также интересно узнать, кто из потоков владеет QMutex'ом в момент QWaitCondition::wakeAll() ? Ведь, по сути Mutex'а им должен владеть лишь один поток. А значит и выполняться будет в каждый момент времени после QWaitCondition::wakeAll() лишь один поток. Но в чём же тогда смысл многопоточности? Это пример из документации и мне не очень понятно где тут многопоточность, когда они будут запускаться последовательно... Заранее спасибо за помощь.

main.cpp

#include <QApplication>
#include "actionthread.h"
#include "widget.h"

QMutex         qmt;
QWaitCondition condition;

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    ActionThread a_1(1), a_2(2), a_3(3);

    a_1.start();
    a_2.start();
    a_3.start();

    Widget w;
    w.show();

    return app.exec();
}

actionthread.h

#ifndef ACTIONTHREAD_H
#define ACTIONTHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QDebug>
#include <QDateTime>

extern QMutex qmt;
extern QWaitCondition condition;

class ActionThread : public QThread
{
    Q_OBJECT
    int id;
public:
    ActionThread(int _id, QObject *parent = 0);
    void run() override;
    void print();
};

#endif // ACTIONTHREAD_H

actionthread.cpp

#include "actionthread.h"

ActionThread::ActionThread(int _id, QObject *parent) : QThread(parent), id(_id)
{

}

void ActionThread::print(){
    qDebug() << "Current thread has id:" << id << QDateTime::currentDateTime();
    sleep(100);
    qDebug() << "I slept" << id << QDateTime::currentDateTime();
}

void ActionThread::run() {
    forever{
        qmt.lock();
        condition.wait(&qmt);
        print();
        qmt.unlock();
    }
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QDebug>
#include <QKeyEvent>
#include <QTimer>
#include "actionthread.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
    void keyPressEvent(QKeyEvent *event);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::keyPressEvent(QKeyEvent *event){
    qDebug() << QChar(event->key());
    condition.wakeAll();
}

Ответы (1 шт):

Автор решения: Sergey Tatarincev

а сколь по времени ждали? QTread::sleep(int) это ожидание В СЕКУНДАХ. это первое. Далее, следует учитывать что:

Avoid using this function if you need to wait for a given condition to change. Instead, connect a slot to the signal that indicates the change or use an event handler (see QObject::event()).

И вообще, постарайтесь избегать QThread:sleep (msleep() и usleep()), поскольку они блокируют эвентлуп.

Еще важно отметить что использование QThread наследованием идея неверная, на что указывает разработчик QT. более подробно предлагаю ознакомиться с этим здесь: https://habr.com/ru/post/150274/

→ Ссылка