添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have simple app with two threads: mainThread and one for heavy calculations.

MainWindow ( mainThread ):

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    ui->setupUi(this);
    thread = new QThread(this);
    worker = new Worker;
    connect(this, &MainWindow::start, worker, &Worker::calculate);
    worker->moveToThread(thread);
    thread->start();
    emit start();
MainWindow::~MainWindow()
    thread->quit();
    qInfo()<<"BEFORE WAIT";
    thread->wait();
    qInfo()<<"AFTER WAIT";
    delete ui;

The secondThread ( heavy calculations ):

void Worker::calculate()
    double z = 21;
    for(int i=0;i<100000000;i++)
        if(i%10000000 == 0) // only to show, the second thread works
            qDebug()<<i;
        z+=qSin(i*0.32)*qCos(i/2*0.31); // heavy calculations
        z+=1000/(i+1);
    qDebug()<<"END";

When I close app using X button and calculations are in progress, everything is ok. In mainThread I wait on thread->wait() and when the second thread ends work - app is closed.

Now I add only one line to my code:

void Worker::calculate()
    double z = 21;
    for(int i=0;i<100000000;i++)
        if(i%10000000 == 0)
            qDebug()<<i;
        z+=qSin(i*0.32)*qCos(i/2*0.31);
        z+=1000/(i+1);
    QCoreApplication::processEvents();  // new Line
    qDebug()<<"END";

I do the same: close app using X button, when calculations are in progress. I wait on thread->wait(), I see on debuq END, but my app is not closed - I still wait on thread->wait(). Why QCoreApplication::processEvents() blocks QThread::wait(), when QThread finished work?

EDIT:

Full code of my App:

main.cpp

#include <QApplication>
#include "mainwindow.h"
int main(int argc, char **argv)
  QApplication app(argc, argv);
  MainWindow mw;
  mw.show();
  return app.exec();

mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    ui->setupUi(this);
    thread = new QThread(this);
    worker = new Worker;
    connect(this, &MainWindow::start, worker, &Worker::calculate);
    worker->moveToThread(thread);
    thread->start();
    emit start();
MainWindow::~MainWindow()
    thread->quit();
    qInfo()<<"BEFORE WAIT";
    thread->wait();
    qInfo()<<"AFTER WAIT";
    delete ui;

mainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include <worker.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    QThread *thread;
    Worker *worker;
signals:
    void start();
#endif // MAINWINDOW_H

worker.h:

#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QtMath>
#include <QCoreApplication>
#include <QDebug>
class Worker: public QObject
    Q_OBJECT
public:
    Worker();
public slots:
    void calculate();
#endif // WORKER_H

worker.cpp

#include "worker.h"
Worker::Worker()
void Worker::calculate()
    double z = 21;
    for(long long i=0;i<10000000000;i++)
        if(i%10000000 == 0) // only to show, the second thread works
            qDebug()<<i;
        z+=qSin(i*0.32)*qCos(i/2*0.31); // heavy calculations
        z+=1000/(i+1);
    QCoreApplication::processEvents();
    qDebug()<<"END";
QT       += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
    main.cpp \
    mainwindow.cpp \
    worker.cpp
HEADERS += \
    mainwindow.h \
    worker.h
FORMS += \
    mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
                Your use of QThread is completely wrong. You cannot call application's processEvents() from another thread. It just does not work like that. You can only call mthods of a QObject from the thread in which the QObject lives (well, there are a few exceptional usecases to this rule, but they are definitely not your case). Btw. what is this call to processEvets() supposed to actually do? What events should it process? And why?
– HiFile.app - best file manager
                Nov 15, 2021 at 11:38
                @V.K. In my example processEvents() no make sense. I know it. There are no events to process. This is simple app, only to show my problem. I can execute that method in any thread. I execute it on my second thread ( no make real sense ) and I see BUG. There is on windows 10 QT 5.15.1. I check on linux 5.9 and here everything is fine.
– juga92
                Nov 15, 2021 at 14:38
                @V.K. Not sure I follow.  Where did you read that "QCoreApplication::processEvents() is not supposed to be called from other than main thread" ?
– G.M.
                Nov 15, 2021 at 19:33
                OK, my mistake. processEvents() is marked as-thread safe so it probably should be OK to call it from another thread.
– HiFile.app - best file manager
                Nov 16, 2021 at 8:10
                I was experimenting with the example a bit and I can confirm this strange behavior. I also found that if you use connect(thread, &QThread::started, worker, &Worker::calculate); instead of your version of connect(...), then it works as expected. But I have no idea why. We need someone more knowledgeable.
– HiFile.app - best file manager
                Nov 16, 2021 at 8:46
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.