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. QThread freezing the UI!
QtWS25 Last Chance

QThread freezing the UI!

Scheduled Pinned Locked Moved General and Desktop
qthreadthread
12 Posts 4 Posters 5.7k 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.
  • rkhaotixR Offline
    rkhaotixR Offline
    rkhaotix
    wrote on last edited by
    #1

    Good day to everyone!
    Here I am again to ask for help!

    In my project I'm using a thread to perform a export process. The export process consists in convert a database model in a SQL script and export snippets of the script to the database server.

    Well, for small models ( ~200 objects) everything is running fine. But when I try to export a huge model the process runs flawlessly until it reaches 70-80% and then the thread gradually start to drain one core of my CPU freezing the entire UI until the ends of its job. I've tried everything to solve but no success...

    Basically I've have two classes involved: a worker and the form to configure the export. In my code I have something like this:

    // Export form
    ExportForm::ExportForm(...)
    {
      export_thread=new QThread(this);
      export_worker.moveToThread(&export_thread);
    }
    ...
    void ExportForm::exportModel()
    {
      ...
      export_thread->start();
      ...
    }
    
    // Export worker
    ...
    void ExportWorker::exportBuffer(...)
    {
      ...
      while(!buffer.atEnd() && !export_cancelled)
     {
       //performing lots of operations here.
      QThread::msleep(50);
     }
    }
    

    The export_cancelled flag is activated from a slot connected in the ExportForm to give user the ability to abort the process anytime.

    I've read somewhere that putting a thread to work with a loop can cause the mentioned behavior (CPU drain and UI freeze). But I need the export to work that way. Someone have any suggestion? A better approach?
    I'm quite confusing and frustrated with all this and any help is welcome!

    P.S.: Sorry about my English!

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      Are you sure that your function is getting executed in the new thread ? I'm thinking that your UI thread only must be doing export task. This must be the reason for hang of UI. Did you put connect statement for thread start and your slots ?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      3
      • rkhaotixR Offline
        rkhaotixR Offline
        rkhaotix
        wrote on last edited by
        #3

        Yes. I'm connecting QThread::started to the ExportWorker::exportBuffer. I'll double check if the thread executing the process is the same as the UI. Thanks!

        1 Reply Last reply
        0
        • rkhaotixR Offline
          rkhaotixR Offline
          rkhaotix
          wrote on last edited by rkhaotix
          #4

          Confirming that the threads are different... Below a simple output.
          Each thread prints its own address (converted to ulong) and where they are (Worker or Form)...

          Form - Thread: 9047552
          Worker - Thread: 54738656
          Worker - Thread: 54738656
          Worker - Thread: 54738656
          Form - Thread: 9047552
          Worker - Thread: 54738656
          Worker - Thread: 54738656
          Worker - Thread: 54738656
          Worker - Thread: 54738656
          Form - Thread: 9047552
          Form - Thread: 9047552
          
          1 Reply Last reply
          0
          • A Offline
            A Offline
            andsun
            wrote on last edited by
            #5
            This post is deleted!
            1 Reply Last reply
            0
            • A Offline
              A Offline
              andsun
              wrote on last edited by
              #6

              How about trying to fork() it?

              rkhaotixR 1 Reply Last reply
              0
              • A Offline
                A Offline
                andsun
                wrote on last edited by
                #7

                Another thing that comes to mind is concurrent programming, read about that this weekend and guess it might be an idea to try as good as any other.

                1 Reply Last reply
                0
                • A andsun

                  How about trying to fork() it?

                  rkhaotixR Offline
                  rkhaotixR Offline
                  rkhaotix
                  wrote on last edited by
                  #8

                  @andsun Fork a thread? How to do that?

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    andsun
                    wrote on last edited by
                    #9

                    check out this fork smaple

                    1 Reply Last reply
                    0
                    • JKSHJ Offline
                      JKSHJ Offline
                      JKSH
                      Moderators
                      wrote on last edited by
                      #10

                      @andsun said:

                      check out this fork smaple

                      There is no need to fork() if you use QThread.

                      @rkhaotix said:

                      Confirming that the threads are different... Below a simple output.
                      Each thread prints its own address (converted to ulong) and where they are (Worker or Form)...

                      Did you print these values from inside ExportWorker::exportBuffer()?

                      I've read somewhere that putting a thread to work with a loop can cause the mentioned behavior (CPU drain and UI freeze). But I need the export to work that way. Someone have any suggestion? A better approach?
                      I'm quite confusing and frustrated with all this and any help is welcome!

                      You need to provide lots more information:

                      1. Do you transfer any data between the 2 threads? If so, how?
                      2. How is the buffer filled?
                      3. Where does the exported data go?
                      4. Which thread creates your QSqlDatabase object?

                      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                      rkhaotixR 1 Reply Last reply
                      1
                      • JKSHJ JKSH

                        @andsun said:

                        check out this fork smaple

                        There is no need to fork() if you use QThread.

                        @rkhaotix said:

                        Confirming that the threads are different... Below a simple output.
                        Each thread prints its own address (converted to ulong) and where they are (Worker or Form)...

                        Did you print these values from inside ExportWorker::exportBuffer()?

                        I've read somewhere that putting a thread to work with a loop can cause the mentioned behavior (CPU drain and UI freeze). But I need the export to work that way. Someone have any suggestion? A better approach?
                        I'm quite confusing and frustrated with all this and any help is welcome!

                        You need to provide lots more information:

                        1. Do you transfer any data between the 2 threads? If so, how?
                        2. How is the buffer filled?
                        3. Where does the exported data go?
                        4. Which thread creates your QSqlDatabase object?
                        rkhaotixR Offline
                        rkhaotixR Offline
                        rkhaotix
                        wrote on last edited by rkhaotix
                        #11

                        @JKSH Thanks for you reply!

                        Answering your questions...

                        1. The only data I transfer between threads are messages and process progress through signals from Worker Thread to Form Thread (UI). Basically a QString and int instances.

                        2. The buffer is filled in the Worker side. It will call the method in database model instance that will produce a QString. After that I iterate line by line in that string using QTextStream.

                        3. The processed SQL for each object is then passed to a instance of a class called Connection (a libpq encapsulation made my me). I don't use the SQL/DB classes provided by Qt.

                        My project is open source but I won't post the code here due its size... If you have any interest here goes the links:

                        Form class: https://github.com/pgmodeler/pgmodeler/blob/develop/libpgmodeler_ui/src/modelexportform.cpp
                        Worker (or Helper) class: https://github.com/pgmodeler/pgmodeler/blob/develop/libpgmodeler_ui/src/modelexporthelper.cpp

                        See methods ModelExportForm::exportModel() and ModelExportHelper::exportBufferToDBMS().

                        1 Reply Last reply
                        0
                        • JKSHJ Offline
                          JKSHJ Offline
                          JKSH
                          Moderators
                          wrote on last edited by
                          #12

                          Hi @rkhaotix,

                          I had a quick look at your code. It's too big for me to go through properly, and I didn't spot anything obvious that maxes out your CPU.

                          However, I noticed a few things which might be related:

                          • Your ModelExportHelper constructor is run in the main thread, so it opens the DB connection in the main thread. Are you sure you can use that connection in the worker thread after this?
                          • In line 56 of modelexportform.cpp: the lambda runs in the signalling (GUI) thread, not the worker thread. Note that, while the QThread manages the worker thread, the QThread object itself lives in the GUI thread.
                          • Your ModelExportHelper uses some GUI-related classes: QGraphicsView, QPixmap. These classes must only be used in the GUI thread.
                          • Your ModelExportHelper includes "modelwidget.h". Why? Widgets must only be used in the GUI thread.

                          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                          1 Reply Last reply
                          1

                          • Login

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