简体   繁体   中英

Thread executed only once

I try to implement this: when app is started I need to create multiple threads that would use the same QDialog window to get messages from user. When thread is started, it asks user for input and if button OK pressed, it prints the message to console. I can't figure out why but I get dialog window only once and after that it prints my one message to console and application finishes.

Here's how I describe dialog window:

#include <QtWidgets>

class MyDialog : public QDialog
{
    Q_OBJECT
public:
    QWaitCondition* condition;

    explicit MyDialog(QWidget *parent = 0);

signals:
    void got_message(QString);
public slots:
    void show_message_input();
    void show_message();
private:
    QLabel* message_label;
    QVBoxLayout* vbox;
    QHBoxLayout* hbox;
    QLineEdit* message_input;
    QDialogButtonBox* dialog_buttons;

};

MyDialog::MyDialog(QWidget *parent) : QDialog(parent)
{
    setModal(true);

    message_label = new QLabel("Message");
    message_input = new QLineEdit();

    dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);

    hbox = new QHBoxLayout();
    hbox->addWidget(message_label);
    hbox->addWidget(message_input);

    vbox = new QVBoxLayout();
    vbox->addLayout(hbox);
    vbox->addWidget(dialog_buttons);

    setLayout(vbox);

    connect(dialog_buttons, SIGNAL(accepted()), this, SLOT(accept()));
    connect(dialog_buttons, SIGNAL(rejected()), this, SLOT(reject()));

    condition = new QWaitCondition();
}

void MyDialog::show_message_input()
{
    int result = this->exec();
    if (result == QDialog::Accepted)
    {
        emit got_message(message_input->text());
        condition->wakeAll();
    }
}

Here's MyThread class:

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(int id, MyDialog* window, QObject *parent = 0);

signals:
    void show_input();
public slots:
    void print_message(QString);
private:
    static QMutex mutex;
    static QMutex mutex2;
    MyDialog* window;
    int id;
    void run();
    void get_captcha_value();
};

QMutex MyThread::mutex;
QMutex MyThread::mutex2;

MyThread::MyThread(int id, MyDialog* window, QObject *parent) :
    QThread(parent)
{
    this->id = id;
    this->window = window;

    connect(this, SIGNAL(show_input()), this->window, SLOT(show_message_input()));
}

void MyThread::get_captcha_value()
{
    QMutexLocker lock(&mutex);
    connect(this->window, SIGNAL(got_message(QString)), SLOT(print_message(QString)));
    emit show_input();
    mutex2.lock();
    window->condition->wait(&mutex2);
    mutex2.unlock();
}

void MyThread::run()
{
    mutex.lock();
    qDebug() << "Starting thread " << id;
    mutex.unlock();
    get_captcha_value();
    mutex.lock();
    qDebug() << "Finishing thread " << id;
    mutex.unlock();
}

void MyThread::print_message(QString message)
{
    qDebug() << message;
    QObject::disconnect(this, SLOT(print_message(QString)));
}

And main function:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyDialog* window = new MyDialog();
    QList<MyThread*> threads;
    for(int i = 0; i < 5; i++)
    {
        MyThread* thread = new MyThread(i, window);
        threads << thread;
        thread->start();
    }
    return a.exec();
}

The first problem you have is that you're inheriting from QThread. Unless you're wanting to re-write how Qt handles threading, you're doing it wrong! .

What you need to do is have a class that inherits from QObject and move the instances to a new thread. The main problem from inheriting QThread is that it can cause confusion about thread affinity (which thread an object is running on).

Also, creating more threads than processor cores is just a waste of resources.

I suggest you read this article on how to use Qt threading and stop inheriting from QThread.

Finally, the use of QMutex is to protect multiple threads accessing the same data simultaneously. You should be able to remove all of them in the code you've shown. Emitting signals with data from one thread to be received by a slot on another thread is the preferred method in Qt.

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