Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    QThread freezing the UI!

    General and Desktop
    qthread thread
    4
    12
    5011
    Loading More Posts
    • 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.
    • rkhaotix
      rkhaotix last edited by

      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 Reply Quote 0
      • dheerendra
        dheerendra Qt Champions 2022 last edited by

        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 Reply Quote 3
        • rkhaotix
          rkhaotix last edited by

          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 Reply Quote 0
          • rkhaotix
            rkhaotix last edited by rkhaotix

            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 Reply Quote 0
            • A
              andsun last edited by

              This post is deleted!
              1 Reply Last reply Reply Quote 0
              • A
                andsun last edited by

                How about trying to fork() it?

                rkhaotix 1 Reply Last reply Reply Quote 0
                • A
                  andsun last edited by

                  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 Reply Quote 0
                  • rkhaotix
                    rkhaotix @andsun last edited by

                    @andsun Fork a thread? How to do that?

                    1 Reply Last reply Reply Quote 0
                    • A
                      andsun last edited by

                      check out this fork smaple

                      1 Reply Last reply Reply Quote 0
                      • JKSH
                        JKSH Moderators last edited by

                        @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

                        rkhaotix 1 Reply Last reply Reply Quote 1
                        • rkhaotix
                          rkhaotix @JKSH last edited by rkhaotix

                          @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 Reply Quote 0
                          • JKSH
                            JKSH Moderators last edited by

                            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 Reply Quote 1
                            • First post
                              Last post