Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Question about QThread object deletion
QtWS25 Last Chance

Question about QThread object deletion

Scheduled Pinned Locked Moved Solved General and Desktop
threadingoopc++
11 Posts 5 Posters 895 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Kirill Gusarev
    28 Apr 2024, 15:25

    Hi smart guys! I have doubts about the correctness of following code:
    [mainwindow.cpp]

    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        thread = new QThread(this);
        connect(this, SIGNAL(destroyed()),
                thread, SLOT(quit()));
    
        worker = new IanColemanSeleniumWorker();
        connect(this, SIGNAL(startWork(uint64_t)),
                worker, SLOT(run(uint64_t)));
        worker->moveToThread(thread);
        thread->start();
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    I wrote this code according to the video guide.
    I'm worried about the line "thread = new QThread(this);". Is "this" argument necessary here? Please pay attention to line "connect(this, SIGNAL(destroyed()), thread, SLOT(quit()));".
    I want the thread to exit gracefully when closing the application. Should a thread have a parent?

    P Offline
    P Offline
    Pl45m4
    wrote on 28 Apr 2024, 16:04 last edited by Pl45m4
    #2

    @Kirill-Gusarev said in Question about QThread object deletion:

    I'm worried about the line "thread = new QThread(this);". Is "this" argument necessary here?

    It's not wrong, but not needed,

    Please pay attention to line "connect(this, SIGNAL(destroyed()), thread, SLOT(quit()));".
    I want the thread to exit gracefully when closing the application. Should a thread have a parent?

    since, when you want have a clean worker every time, you can do something like:

    MainWindow::spawnWorker(uint64_t workerArg) 
    {
       QThread *thread = new QThread();
       IanColemanSeleniumWorker *worker = new IanColemanSeleniumWorker();
       worker->moveToThread(thread);
    
       // maybe error handling
       // post error to MainWindow
       connect( worker, &IanColemanSeleniumWorker::error, this, &MainWindow::errorString);
    
       connect( this, &MainWindow::startWork, worker, &IanColemanSeleniumWorker::run);
       // emit a finished() signal in your worker, once you are done
       connect( worker, &IanColemanSeleniumWorker::finished, thread, &QThread::quit);
       connect( worker, &IanColemanSeleniumWorker::finished, worker, &IanColemanSeleniumWorker::deleteLater);
       connect( thread, &QThread::finished, thread, &QThread::deleteLater);
    
       thread->start();
       emit startWork(workerArg);
    }
    

    This will create a new thread and worker, let the worker do its job and then they are cleaned up properly without the need to being child of MainWindow / this.
    Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

    Also using the above approach you might need to handle the destroyed signal, like you did in your code, to stop/interrupt running workers when you want to exit.


    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    K 3 Replies Last reply 28 Apr 2024, 16:21
    6
    • P Pl45m4
      28 Apr 2024, 16:04

      @Kirill-Gusarev said in Question about QThread object deletion:

      I'm worried about the line "thread = new QThread(this);". Is "this" argument necessary here?

      It's not wrong, but not needed,

      Please pay attention to line "connect(this, SIGNAL(destroyed()), thread, SLOT(quit()));".
      I want the thread to exit gracefully when closing the application. Should a thread have a parent?

      since, when you want have a clean worker every time, you can do something like:

      MainWindow::spawnWorker(uint64_t workerArg) 
      {
         QThread *thread = new QThread();
         IanColemanSeleniumWorker *worker = new IanColemanSeleniumWorker();
         worker->moveToThread(thread);
      
         // maybe error handling
         // post error to MainWindow
         connect( worker, &IanColemanSeleniumWorker::error, this, &MainWindow::errorString);
      
         connect( this, &MainWindow::startWork, worker, &IanColemanSeleniumWorker::run);
         // emit a finished() signal in your worker, once you are done
         connect( worker, &IanColemanSeleniumWorker::finished, thread, &QThread::quit);
         connect( worker, &IanColemanSeleniumWorker::finished, worker, &IanColemanSeleniumWorker::deleteLater);
         connect( thread, &QThread::finished, thread, &QThread::deleteLater);
      
         thread->start();
         emit startWork(workerArg);
      }
      

      This will create a new thread and worker, let the worker do its job and then they are cleaned up properly without the need to being child of MainWindow / this.
      Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

      Also using the above approach you might need to handle the destroyed signal, like you did in your code, to stop/interrupt running workers when you want to exit.

      K Offline
      K Offline
      Kirill Gusarev
      wrote on 28 Apr 2024, 16:21 last edited by
      #3

      @Pl45m4 Your code is beautiful.
      Большое спасибо!

      Ъуъ

      1 Reply Last reply
      0
      • K Kirill Gusarev has marked this topic as solved on 28 Apr 2024, 16:22
      • P Pl45m4
        28 Apr 2024, 16:04

        @Kirill-Gusarev said in Question about QThread object deletion:

        I'm worried about the line "thread = new QThread(this);". Is "this" argument necessary here?

        It's not wrong, but not needed,

        Please pay attention to line "connect(this, SIGNAL(destroyed()), thread, SLOT(quit()));".
        I want the thread to exit gracefully when closing the application. Should a thread have a parent?

        since, when you want have a clean worker every time, you can do something like:

        MainWindow::spawnWorker(uint64_t workerArg) 
        {
           QThread *thread = new QThread();
           IanColemanSeleniumWorker *worker = new IanColemanSeleniumWorker();
           worker->moveToThread(thread);
        
           // maybe error handling
           // post error to MainWindow
           connect( worker, &IanColemanSeleniumWorker::error, this, &MainWindow::errorString);
        
           connect( this, &MainWindow::startWork, worker, &IanColemanSeleniumWorker::run);
           // emit a finished() signal in your worker, once you are done
           connect( worker, &IanColemanSeleniumWorker::finished, thread, &QThread::quit);
           connect( worker, &IanColemanSeleniumWorker::finished, worker, &IanColemanSeleniumWorker::deleteLater);
           connect( thread, &QThread::finished, thread, &QThread::deleteLater);
        
           thread->start();
           emit startWork(workerArg);
        }
        

        This will create a new thread and worker, let the worker do its job and then they are cleaned up properly without the need to being child of MainWindow / this.
        Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

        Also using the above approach you might need to handle the destroyed signal, like you did in your code, to stop/interrupt running workers when you want to exit.

        K Offline
        K Offline
        Kirill Gusarev
        wrote on 28 Apr 2024, 16:27 last edited by
        #4

        @Pl45m4 what does "c'tor" mean?

        Ъуъ

        P 1 Reply Last reply 28 Apr 2024, 16:51
        0
        • K Kirill Gusarev
          28 Apr 2024, 16:27

          @Pl45m4 what does "c'tor" mean?

          P Offline
          P Offline
          Pl45m4
          wrote on 28 Apr 2024, 16:51 last edited by Pl45m4
          #5

          @Kirill-Gusarev said in Question about QThread object deletion:

          what does "c'tor" mean?

          constructor

          If your IanColemanSeleniumWorker class has private members:

          IanColemanSeleniumWorker::IanColemanSeleniumWorker(QObject *parent)
            : QObject{parent}
          {
            // DONT do something like that here
            // allocate memory and assign data AFTER the object was moved
            // ideally init your members at the beginning of your run function
            m_workerData = new SomeDataClass();
            m_intptr = new int;
          }
          

          Better:

          IanColemanSeleniumWorker::run(uint64_t int)
          {
             m_data = new SomeDataClass();
          
             // do work
             // . . .
             // . . . 
          
             emit finished(); // send finished signal when work is done
          }
          

          because of these lines

             // ...
            IanColemanSeleniumWorker *worker = new IanColemanSeleniumWorker(); // worker and all its childs in main thread
             worker->moveToThread(thread); // worker moved
             // worker belongs to "thread" Thread from now on
             // ...
          

          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          0
          • P Pl45m4
            28 Apr 2024, 16:04

            @Kirill-Gusarev said in Question about QThread object deletion:

            I'm worried about the line "thread = new QThread(this);". Is "this" argument necessary here?

            It's not wrong, but not needed,

            Please pay attention to line "connect(this, SIGNAL(destroyed()), thread, SLOT(quit()));".
            I want the thread to exit gracefully when closing the application. Should a thread have a parent?

            since, when you want have a clean worker every time, you can do something like:

            MainWindow::spawnWorker(uint64_t workerArg) 
            {
               QThread *thread = new QThread();
               IanColemanSeleniumWorker *worker = new IanColemanSeleniumWorker();
               worker->moveToThread(thread);
            
               // maybe error handling
               // post error to MainWindow
               connect( worker, &IanColemanSeleniumWorker::error, this, &MainWindow::errorString);
            
               connect( this, &MainWindow::startWork, worker, &IanColemanSeleniumWorker::run);
               // emit a finished() signal in your worker, once you are done
               connect( worker, &IanColemanSeleniumWorker::finished, thread, &QThread::quit);
               connect( worker, &IanColemanSeleniumWorker::finished, worker, &IanColemanSeleniumWorker::deleteLater);
               connect( thread, &QThread::finished, thread, &QThread::deleteLater);
            
               thread->start();
               emit startWork(workerArg);
            }
            

            This will create a new thread and worker, let the worker do its job and then they are cleaned up properly without the need to being child of MainWindow / this.
            Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

            Also using the above approach you might need to handle the destroyed signal, like you did in your code, to stop/interrupt running workers when you want to exit.

            K Offline
            K Offline
            Kirill Gusarev
            wrote on 30 Apr 2024, 03:16 last edited by
            #6

            @Pl45m4 said in Question about QThread object deletion:

            Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

            What will happen if I allocate new objects in the worker's constructor?

            Ъуъ

            J S 2 Replies Last reply 30 Apr 2024, 06:21
            0
            • K Kirill Gusarev
              30 Apr 2024, 03:16

              @Pl45m4 said in Question about QThread object deletion:

              Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

              What will happen if I allocate new objects in the worker's constructor?

              J Offline
              J Offline
              jsulm
              Lifetime Qt Champion
              wrote on 30 Apr 2024, 06:21 last edited by
              #7

              @Kirill-Gusarev The explanation provided by @Pl45m4 answers your question: worker constructor is not running in the other thread, so everything allocated in the constructor is allocated in the thread where the worker is created.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              K 1 Reply Last reply 1 May 2024, 03:00
              0
              • K Kirill Gusarev
                30 Apr 2024, 03:16

                @Pl45m4 said in Question about QThread object deletion:

                Keep in mind not to allocate new objects in the workers c'tor, because the c'tor is called when the worker is still in MainWindow's main GUI thread.

                What will happen if I allocate new objects in the worker's constructor?

                S Offline
                S Offline
                SimonSchroeder
                wrote on 30 Apr 2024, 06:43 last edited by
                #8

                @Kirill-Gusarev said in Question about QThread object deletion:

                What will happen if I allocate new objects in the worker's constructor?

                This mostly relates to objects derived from QObject. QObject is thread affine which is why you need to use moveToThread(). As said before, the constructor is not yet run inside the new thread, but only the run() method. This rule does not necessarily apply for objects not derived from QObject, but it is certainly easier to follow the rule to not create any object inside the constructor. This also keeps all initialization in one place (i.e. the run() method).

                K 1 Reply Last reply 30 Apr 2024, 09:23
                2
                • S SimonSchroeder
                  30 Apr 2024, 06:43

                  @Kirill-Gusarev said in Question about QThread object deletion:

                  What will happen if I allocate new objects in the worker's constructor?

                  This mostly relates to objects derived from QObject. QObject is thread affine which is why you need to use moveToThread(). As said before, the constructor is not yet run inside the new thread, but only the run() method. This rule does not necessarily apply for objects not derived from QObject, but it is certainly easier to follow the rule to not create any object inside the constructor. This also keeps all initialization in one place (i.e. the run() method).

                  K Offline
                  K Offline
                  kshegunov
                  Moderators
                  wrote on 30 Apr 2024, 09:23 last edited by
                  #9

                  @SimonSchroeder said in Question about QThread object deletion:

                  As said before, the constructor is not yet run inside the new thread, but only the run() method.

                  Just so we are very clear - because the run method is the new thread ...

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  1
                  • J jsulm
                    30 Apr 2024, 06:21

                    @Kirill-Gusarev The explanation provided by @Pl45m4 answers your question: worker constructor is not running in the other thread, so everything allocated in the constructor is allocated in the thread where the worker is created.

                    K Offline
                    K Offline
                    Kirill Gusarev
                    wrote on 1 May 2024, 03:00 last edited by
                    #10

                    @jsulm Why is that bad?

                    Ъуъ

                    J 1 Reply Last reply 2 May 2024, 05:59
                    0
                    • K Kirill Gusarev
                      1 May 2024, 03:00

                      @jsulm Why is that bad?

                      J Offline
                      J Offline
                      jsulm
                      Lifetime Qt Champion
                      wrote on 2 May 2024, 05:59 last edited by
                      #11

                      @Kirill-Gusarev See @SimonSchroeder explanation and also read https://doc.qt.io/qt-6/threads-qobject.html

                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0

                      11/11

                      2 May 2024, 05:59

                      • Login

                      • Login or register to search.
                      11 out of 11
                      • First post
                        11/11
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved