QThread freezes whole app.



  • Today just started exploring QThreads, found it quite hard, especially when in pure C++ using <Thread.h> you can simply create Thread variable and assign any your function and you free to go.
    I need simply run two my different functions which both have loops which going for about the minute.Both functions is from my MainWindow class.

    Here how my constructor looks:

    MWindow::MWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MWindow)
    {
        ui->setupUi(this);
    
        thread1 = new QThread;
        this->moveToThread(thread1);
        connect(thread1, SIGNAL(started()), this, SLOT(myFunction1()));
    
        thread2 = new QThread;
        this->moveToThread(thread2);
        connect(thread2, SIGNAL(started()), this, SLOT(myFunction2()));
    }
    

    And here is my push button slot:

    void MWindow::on_runButton_clicked()
    {
        thread1->start();
        thread2->start();
    }
    

    In output window it display warning: QObject::moveToThread: Widgets cannot be moved to a new thread

    I tried with only one thread first, it working, i mean, whole application freezes while loop is not done, but result of myFunction1() is correct. And after that loop done, the program returns to work and everything fine.

    In second case where is two threads(like in code examples above), app also freezes, but forever, none of two myFunctions is succeed.

    I rly cant understand how to do simplest thing with QThreads - run two functions simultaneously. Please help.


  • Qt Champions 2017

    Hi
    You cannot have QWidgets in other thread than gui thread.
    And you try to move mainwindow to new one. (this->moveToThread(thread1);
    Hence the warning:

    While it possible to use QThread in other ways, i highly recommend using the worker approach.

    https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

    Note that the worker is based on QObject, not QWidget.



  • Hi! The whole process of executing heavy work in Qt is to remove it from the main GUI thread. So you have to create the worker class and implement myFunction1() and myFunction2() there, then connect it.

    Example:

    QThread *thread1 = new QThread();
    Worker *worker1 = new Worker();
    worker->moveToThread(thread1);
    connect(thread1, &QThread::started, worker1, &Worker::myFunction1);
    connect(worker1, &Worker::mySignal1, this, &MWindow::mySlot1);
    connect(worker1, &Worker::finished, thread1, &QThread::quit);
    connect(worker1, &Worker::finished, worker1, &Worker::deleteLater);
    connect(thread1, &QThread::finished, thread1, &QThread::deleteLater);
    thread1->start();
    
    QThread *thread2 = new QThread();
    Worker *worker2 = new Worker();
    worker2->moveToThread(thread2);
    connect(thread2, &QThread::started, worker2, &Worker::myFunction2);
    connect(worker2, &Worker::mySignal2, this, &MWindow::mySlot2);
    connect(worker2, &Worker::finished, thread2, &QThread::quit);
    connect(worker2, &Worker::finished, worker2, &Worker::deleteLater);
    connect(thread2, &QThread::finished, thread2, &QThread::deleteLater);
    thread2->start();
    

    mySignalX will emit the signal of the processing data from the thread to the GUI. mySlotX will display the result. Also finished signal should be emitted to quit from threads. You should call it when the loop is finished.



  • I've already tried use my own custom class which inherit QThread and in that class reimplement void run(); function and it works. But the problem that(as i understand) the only way i can do multithreading - using that reimplemented run.

    So as i understand - my custom class for multithreading can handle only one function(run();).

    I need to make custom class for every different function?



  • Just now i tried simple <thread.h> class from std in my old VS. Damn it's bliss, 2 lines of code - 2 working threads, why the same cant be in Qt?

    Tried same in Qt now, getting errors, code:

    void MWindow::on_doButton_clicked()
    {
        std::thread firs(firstFunction);
        std::thread sec(secondFunction);
    }
    

    Error: C3867: 'MWindow::firstFunction': non-standard syntax; use '&' to create a pointer to member



  • Well, qt is still c++, nothing stopping you from using part of the standart libary.

    That said, fire and forget long functions than run a long time can be done (threaded) via QtConcurrent, thats in your case here, also pretty much a one liner.

    QtConcurrent

    void MWindow::on_doButton_clicked()
    {
        QtConcurrent::run(firstFunction);
        QtConcurrent::run(secondFunction);
    }
    


  • @Engelard

    Hi! You used the wrong and old way of creating threads in Qt, that's why you must use 1 method in the run and create another worker for another method. I suggest you to use it right: How To Really, Truly Use QThreads; The Full Explanation. Using the new method of creating threads, you can create as many threads as you want from the single worker class.

    Also, you can use threads from standard C++:

    #include <thread>
    
    std::thread firs(&MWindow::firstFunction);
    std::thread sec(&MWindow::secondFunction);
    


  • Also, you can use threads from standard C++:

    #include <thread>
    
    std::thread firs(&MWindow::firstFunction);
    std::thread sec(&MWindow::secondFunction);
    

    Well, i tried, and there is like 15 errors appear:

    alt text



  • That said, fire and forget long functions than run a long time can be done (threaded) via QtConcurrent, thats in your case here, also pretty much a one liner.

    QtConcurrent

    void MWindow::on_doButton_clicked()
    {
        QtConcurrent::run(firstFunction);
        QtConcurrent::run(secondFunction);
    }
    

    Well)) for that case, i got 199 errors when i added code as you suggested:

    #include <QtConcurrent/QtConcurrent>
    
    void MWindow::on_doButton_clicked()
    {
        QtConcurrent::run(doProcess);
        QtConcurrent::run(doProcess2);
    }
    


  • I suggest you to use it right: How To Really, Truly Use QThreads; The Full Explanation. Using the new method of creating threads, you can create as many threads as you want from the single worker class.

    Already tried that yesterday night. Everything seems perfect, no errors, but at the run time i got 4 alarms in Application Output about 3 signals in my Worker class and 1 slot. I didnt figure out whats wrong, but now i'm googling such issue

    "QObject::connect: No such signal"
    

    P.S. yes, my slot function in worker class in public slots: and signals: is just signal, they cant be in public.


  • Qt Champions 2017

    @Engelard
    Hi you have included QObject in worker class ?
    class Worker : public QObject {
    Q_OBJECT <<<<<



  • @mrjj ah, forgot about that macro(never notice that, it always awtomaticly was created by QT)

    Now i add it, and it adds me even more errors, but here is whole my code of worker header file:

    #pragma once
    
    #include <QtCore>
    #include <QObject>
    #include <Windows.h>
    
    class TestThreads : public QObject
    {
        Q_OBJECT
    public:
        TestThreads();
    
        static unsigned int addressNow;
        unsigned int addressMAX = 10;
        int myValue;
    
        bool scanDone = false;
    
        DWORD objID;
    
    public slots:
        void scanProcess();
    
    signals:
        void addressFound(unsigned int addr);
        void addressValue(int val);
        void scanFinished();
    };
    
    

    And the result of adding that Q_OBJECT macro is this:

    alt text


  • Qt Champions 2017

    @Engelard
    Well that is a normal case
    Clean your build folder ( just delete all files)
    and then run qmake.
    Then rebuild all and it should be happy.



  • @mrjj now there is new 3 errors)

    alt text


  • Qt Champions 2017

    @Engelard
    Hi
    Its "already defined" so check your .pro file
    if you have the file(s) included twice for some reason.



  • @mrjj nope, everything fine in there, all i have there is mentioned only once


  • Qt Champions 2017

    @Engelard
    hmm.
    what files does class TestThread live it ?
    Also did you give your signals a body in cpp for
    void addressFound(unsigned int addr);
    void addressValue(int val);
    void scanFinished();
    as it seems to complain about those.
    (signals should not have a body)



  • (signals should not have a body)

    OMG, i didnt know, and as habbit i ofcource gave body(definitions) for every signal function.

    Now its working, and threads working perfectly, thank you!


  • Qt Champions 2017

    @Engelard
    Yep its a true classic as normally u must always give a body or it complains about that.
    but signals are just the signatures.



  • @Engelard you need to properly tag people😉
    Anyway QtConcurrent is its own modul, you‘ll need to add it in your pro file as such, as it is stated in the docu

    QT += concurrent

    than it should work, now that you have removed the function body of the signal ☺️


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.