Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. UI Application as thread - CPU Load almost 100%
Forum Updated to NodeBB v4.3 + New Features

UI Application as thread - CPU Load almost 100%

Scheduled Pinned Locked Moved Solved Mobile and Embedded
13 Posts 5 Posters 5.4k Views 2 Watching
  • 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 Offline
    K Offline
    kumararajas
    wrote on 20 May 2016, 12:34 last edited by
    #1

    Hi,
    As per my requirement, After starting up the UI, I need to do some more processing. So, I cannot create QApplication object in my main(). Rather, I call a function in a thread and from that thread, I create QApplication object and running UI as thread.
    Problem with this approach is that,
    I notice that, CPU consumption by my application is always 100%.

    Any thoughts on this?

    Thanks,
    Kumara

    --Kumar

    ? 1 Reply Last reply 20 May 2016, 12:40
    0
    • K kumararajas
      20 May 2016, 12:34

      Hi,
      As per my requirement, After starting up the UI, I need to do some more processing. So, I cannot create QApplication object in my main(). Rather, I call a function in a thread and from that thread, I create QApplication object and running UI as thread.
      Problem with this approach is that,
      I notice that, CPU consumption by my application is always 100%.

      Any thoughts on this?

      Thanks,
      Kumara

      ? Offline
      ? Offline
      A Former User
      wrote on 20 May 2016, 12:40 last edited by
      #2

      @kumararajas Hi! I don't think you can run the GUI in a different thread than the main thread as the documentation says:

      As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.

      K 1 Reply Last reply 20 May 2016, 13:47
      0
      • ? A Former User
        20 May 2016, 12:40

        @kumararajas Hi! I don't think you can run the GUI in a different thread than the main thread as the documentation says:

        As mentioned, each program has one thread when it is started. This thread is called the "main thread" (also known as the "GUI thread" in Qt applications). The Qt GUI must run in this thread. All widgets and several related classes, for example QPixmap, don't work in secondary threads. A secondary thread is commonly referred to as a "worker thread" because it is used to offload processing work from the main thread.

        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 20 May 2016, 13:47 last edited by kshegunov
        #3

        @Wieland said:

        I don't think you can run the GUI in a different thread than the main thread

        Actually, it is possible in principle, but only provided the GUI thread is the only thread accessing the GUI, which mostly defeats the whole purpose of starting a new thread for it. :)

        So, I cannot create QApplication object in my main().

        I don't follow. Why is that? You can start a worker thread and do whatever is you do there, how is this directly impeding you from creating the QApplication object in main.

        Rather, I call a function in a thread and from that thread, I create QApplication object and running UI as thread.

        "How" is key here? Please provide some source.

        Kind regards.

        Read and abide by the Qt Code of Conduct

        1 Reply Last reply
        1
        • K Offline
          K Offline
          kumararajas
          wrote on 23 May 2016, 07:27 last edited by kumararajas
          #4

          The application is that,
          UI is configurable in my system. If the LCD is not connected, I don't need UI Application to be running. So, my main application, checks for the configuration and based on that, I start the UI. That's one thing. And, I do have other processing to be done, apart from displaying the user interface. So, I start the UI, and continue to do my job in the background.

          Do you see any misunderstanding with my thoughts?

          I dont see the reason on "why" GUI cant be in a worker thread and do whatever in my own space, which is as close to UI being run from Main Thread.

          And when I have implemented, yes, I am able to run the UI from the worker thread. I havent tested all Qt features though.

          But the problem I have is, CPU being loaded to 100%. But, I had a way to overcome this by calling pthread_exit soon after creating the thread. It doesnt makes sense to me. But, this pulls the CPU load to minimal.

          Here is how my code looks like -

          int main(void)
          {
          startApp();
          // UI is running in a thread. Let's continue to do other activities.
          }
          
          void startApp()
          {
              pthread_t uiThread;
          
              int argc = 0;
              char *argv[1];
              InputArgs args = {argc, argv};
              int rc = pthread_create(&uiThread, NULL, startUIAsThread, (void*)&args);
              pthread_exit(NULL);
          }
          
          void *startUIAsThread(void *threadArgs)
          {
              InputArgs *args = (struct InputArgs*) threadArgs;
              createUserInterface(*args);
          }
          
          void createUserInterface(InputArgs args)
          {
              QApplication *uiApp = new QApplication(args.argc ,
                                                     args.argv ,
                                                     QApplication::GuiServer);
              uiApp->exec();
          }
          

          Do you see any problem with my code?

          Thanks,
          Kumara

          --Kumar

          K 1 Reply Last reply 23 May 2016, 10:06
          0
          • Q Offline
            Q Offline
            Q139
            wrote on 23 May 2016, 08:27 last edited by
            #5

            Best to place high loads seperate from ui thread but when load gets very high then even windows explorer will hang.

            1 Reply Last reply
            0
            • K kumararajas
              23 May 2016, 07:27

              The application is that,
              UI is configurable in my system. If the LCD is not connected, I don't need UI Application to be running. So, my main application, checks for the configuration and based on that, I start the UI. That's one thing. And, I do have other processing to be done, apart from displaying the user interface. So, I start the UI, and continue to do my job in the background.

              Do you see any misunderstanding with my thoughts?

              I dont see the reason on "why" GUI cant be in a worker thread and do whatever in my own space, which is as close to UI being run from Main Thread.

              And when I have implemented, yes, I am able to run the UI from the worker thread. I havent tested all Qt features though.

              But the problem I have is, CPU being loaded to 100%. But, I had a way to overcome this by calling pthread_exit soon after creating the thread. It doesnt makes sense to me. But, this pulls the CPU load to minimal.

              Here is how my code looks like -

              int main(void)
              {
              startApp();
              // UI is running in a thread. Let's continue to do other activities.
              }
              
              void startApp()
              {
                  pthread_t uiThread;
              
                  int argc = 0;
                  char *argv[1];
                  InputArgs args = {argc, argv};
                  int rc = pthread_create(&uiThread, NULL, startUIAsThread, (void*)&args);
                  pthread_exit(NULL);
              }
              
              void *startUIAsThread(void *threadArgs)
              {
                  InputArgs *args = (struct InputArgs*) threadArgs;
                  createUserInterface(*args);
              }
              
              void createUserInterface(InputArgs args)
              {
                  QApplication *uiApp = new QApplication(args.argc ,
                                                         args.argv ,
                                                         QApplication::GuiServer);
                  uiApp->exec();
              }
              

              Do you see any problem with my code?

              Thanks,
              Kumara

              K Offline
              K Offline
              kshegunov
              Moderators
              wrote on 23 May 2016, 10:06 last edited by kshegunov
              #6

              @kumararajas said:

              Do you see any misunderstanding with my thoughts?

              Well, I wouldn't start the GUI in another thread. I'd do something like this:

              int main(int argc, char ** argv)
              {
                  QApplication app(argc, argv);
                  if (lcdIsConnected())
                      return QApplication::exec();
              
                 doThingsThatDontRequireGUI();
                 return 0;
              }
              

              Do you see any problem with my code?

              A few, yes.

              • Firstly, you're using a very convoluted way to start a thread. If you shall ask, Qt shall provide - simply use QThread.
              • Secondly, pthread_exit(NULL); kills your main thread (where main() is run), which ain't good at all.
              • Thirdly, you create an application object and you never delete it.
              • And lastly, What's QApplication::GuiServer and why are you passing it to the QApplication object?

              So. Try something along the lines of this (main.cpp):

              class AppThread : public QThread
              {
              public:
                  AppThread(int &, char ** &);
              
              protected:
                  void run() override;
              
              private:
                  int & argc;
                  char ** & argv;
              };
              
              AppThread::AppThread(int & n, char ** & nstr)
                  : argc(n), argv(nstr)
              {
              }
              
              void AppThread::run()
              {
                  QApplication app(argc, argv);
                  app.exec();
              }
              
              int main(int argc, char ** argv)
              {
                  AppThread thread(argc, argv);
                  thread.start();
                  
                  // ... Do other stuff ...
              
                  thread.wait();
                  return 0;
              }
              

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              1
              • K Offline
                K Offline
                kumararajas
                wrote on 24 May 2016, 07:05 last edited by kumararajas
                #7

                Hi,
                Here are my thoughts and answers..

                First of all -

                int main(int argc, char ** argv)
                {
                    QApplication app(argc, argv);
                    if (lcdIsConnected())
                        return QApplication::exec();
                
                   doThingsThatDontRequireGUI();
                   return 0;
                }
                

                In the above code. If LCD is connected, then exec() gets executed, which is a blocking call. And doThingsThatDontRequireGUI(); never gets called. This is not what I want. Even if LCD is present or not, I should be able to execute doThingsThatDontRequireGUI();

                Answering to the points.
                > Firstly, you're using a very convoluted way to start a thread. If you shall ask, Qt shall provide - simply use QThread.
                That is a good idea. I can use QThread. However I just went with posix function. I can use that for sure.
                > Secondly, pthread_exit(NULL); kills your main thread (where main() is run), which ain't good at all.
                Agree with you. This is a bad idea. I had this statement to reduce the CPU load. But I know this is not good at all.
                > Thirdly, you create an application object and you never delete it.
                I haven't deleted because the object's life time is till the end of application. Agree, I need to free up the memory during destruction process.
                > And lastly, What's QApplication::GuiServer and why are you passing it to the QApplication object?
                Thjs is something I have tried out.When we run Qt application on embedded platform, we should be passing -qws. I just don't want to pass this option for my application needs. This helps me to start the QWS server by itself rather than passing the argument -qws.

                I am going to give a try with the example you have provided. All I need is CPU load to be as less as possible. I will test and keep you posted with the results.

                Thank you,
                Kumara

                --Kumar

                1 Reply Last reply
                0
                • jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on 24 May 2016, 07:19 last edited by
                  #8

                  Why not execute doThingsThatDontRequireGUI() in another thread?

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

                  1 Reply Last reply
                  1
                  • K Offline
                    K Offline
                    kshegunov
                    Moderators
                    wrote on 25 May 2016, 11:47 last edited by kshegunov
                    #9

                    @kumararajas

                    In the above code. If LCD is connected, then exec() gets executed, which is a blocking call. And doThingsThatDontRequireGUI(); never gets called. This is not what I want. Even if LCD is present or not, I should be able to execute doThingsThatDontRequireGUI();

                    You can do that in the main thread, but I see your point. If doThingsThatDontRequireGUI() is long it'd hang up the main thread. But then, as @jsulm said, why not thread that particular function?

                    For example:

                    class MyInitThread : public QThread
                    {
                    protected:
                        void run() override;
                    };
                    
                    void MyInitThread::run()
                    {
                        doThingsThatDontRequireGUI(); //< Do whatever it is you require for initialization here
                    }
                    
                    int main(int argc, char ** argv)
                    {
                        MyInitThread initThread;
                        initThread.start();
                    
                        int retValue = 0;
                           
                        if (lcdIsConnected())  {
                            QApplication app(argc, argv);
                            retValue = QApplication::exec();
                        }
                    
                        initThread.wait();
                        return retValue;
                    }
                    

                    I haven't deleted because the object's life time is till the end of application. Agree, I need to free up the memory during destruction process.

                    Although the OS probably cleans up the object, I firmly believe you should take care to free your objects.

                    This helps me to start the QWS server by itself rather than passing the argument -qws.

                    Fair enough.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    0
                    • K Offline
                      K Offline
                      kumararajas
                      wrote on 27 May 2016, 05:47 last edited by
                      #10

                      Here I am with the results.

                      When I create a worker thread and create QApplication in it, I get this message -

                      WARNING: QApplication was not created in the main() thread.
                      

                      And UI doesn't comes up.

                      I wonder why Qt looks for Main Thread during instantiation of QApplication.

                      I like the approach of creating a thread and performing the operations that does not depends on GUI, the business logics.

                      Here is the reason that, I dont want to create QApplication and get blocked by calling exec in the main().
                      I have main(), that creates various child processes for various operations. One of the process is meant for UI. And the UI child process is suppose to create UI and also look for other operations.

                      I can do that too, like creating a thread for such other operations and get the main thread of child process blocked.

                      My perception was that, main thread and worker threads are same. Just that main thread is not user created one.

                      --Kumar

                      K 1 Reply Last reply 27 May 2016, 06:22
                      0
                      • K kumararajas
                        27 May 2016, 05:47

                        Here I am with the results.

                        When I create a worker thread and create QApplication in it, I get this message -

                        WARNING: QApplication was not created in the main() thread.
                        

                        And UI doesn't comes up.

                        I wonder why Qt looks for Main Thread during instantiation of QApplication.

                        I like the approach of creating a thread and performing the operations that does not depends on GUI, the business logics.

                        Here is the reason that, I dont want to create QApplication and get blocked by calling exec in the main().
                        I have main(), that creates various child processes for various operations. One of the process is meant for UI. And the UI child process is suppose to create UI and also look for other operations.

                        I can do that too, like creating a thread for such other operations and get the main thread of child process blocked.

                        My perception was that, main thread and worker threads are same. Just that main thread is not user created one.

                        K Offline
                        K Offline
                        kshegunov
                        Moderators
                        wrote on 27 May 2016, 06:22 last edited by kshegunov
                        #11

                        @kumararajas said:

                        When I create a worker thread and create QApplication in it, I get this message

                        There's a reason for that. Qt has internally quite a lot of statics and it keeps track of them. They are unprotected for the most part and can't be just accessed from any thread. You get that message, because I misled you, sorry for that. QThread's constructor will ultimately set the main thread internally, so that's why you get the warning. Here's a much better example, that might run okay (or it might not):

                        #include "mainwindow.h"
                        
                        #include <QApplication>
                        #include <thread>
                        
                        void fakeMain(int argc, char ** argv)
                        {
                        	QApplication a(argc, argv);
                        	MainWindow w;
                        	w.show();
                        
                        	QApplication::exec();
                        }
                        
                        int main(int argc, char ** argv)
                        {
                        	std::thread fakeMainThread(fakeMain, argc, argv);
                        
                        	fakeMainThread.join(); //< This is really important, do not remove it.
                        	return 0;
                        }
                        

                        EDIT: I tested the example on my Debian it appears to run okay.

                        Still, I continue to believe you should move your code out of main, put it in a worker thread and run Qt in the main one.

                        My perception was that, main thread and worker threads are same. Just that main thread is not user created one.

                        They are in principle, yes.

                        Read and abide by the Qt Code of Conduct

                        K 1 Reply Last reply 27 May 2016, 07:41
                        1
                        • K kshegunov
                          27 May 2016, 06:22

                          @kumararajas said:

                          When I create a worker thread and create QApplication in it, I get this message

                          There's a reason for that. Qt has internally quite a lot of statics and it keeps track of them. They are unprotected for the most part and can't be just accessed from any thread. You get that message, because I misled you, sorry for that. QThread's constructor will ultimately set the main thread internally, so that's why you get the warning. Here's a much better example, that might run okay (or it might not):

                          #include "mainwindow.h"
                          
                          #include <QApplication>
                          #include <thread>
                          
                          void fakeMain(int argc, char ** argv)
                          {
                          	QApplication a(argc, argv);
                          	MainWindow w;
                          	w.show();
                          
                          	QApplication::exec();
                          }
                          
                          int main(int argc, char ** argv)
                          {
                          	std::thread fakeMainThread(fakeMain, argc, argv);
                          
                          	fakeMainThread.join(); //< This is really important, do not remove it.
                          	return 0;
                          }
                          

                          EDIT: I tested the example on my Debian it appears to run okay.

                          Still, I continue to believe you should move your code out of main, put it in a worker thread and run Qt in the main one.

                          My perception was that, main thread and worker threads are same. Just that main thread is not user created one.

                          They are in principle, yes.

                          K Offline
                          K Offline
                          kumararajas
                          wrote on 27 May 2016, 07:41 last edited by
                          #12

                          @kshegunov

                          That's a good thought!

                          I live in a basic environment that doesn't support C++ 11, So, std::thread won't work for me.

                          However, I can use posix API pthread_create. This goes back to the loop. If I replace std::thread with pthread_create in the example you have provided, I arrive at my old example (in the top of this conversation)

                          One eye opener, which I have got in your example is pthread_join

                          In my example, I was using pthread_exit which is absolutely not accepted to terminate the calling thread, in my case it was a main thread. It was a blunder.

                          Instead of that, now I have updated my code to call pthread_join. This works charm. I am able to bring down the CPU to a least number. This was an outcome of my basic testing. I will continue to perform various tests further.

                          However, that's a good point on moving my business code from main to the worker thread. I shall think about it.

                          Thanks for all those healthy discussions. I am glad that, I got a chance to discuss a lot with the experts like you!

                          --Kumar

                          K 1 Reply Last reply 30 May 2016, 11:33
                          0
                          • K kumararajas
                            27 May 2016, 07:41

                            @kshegunov

                            That's a good thought!

                            I live in a basic environment that doesn't support C++ 11, So, std::thread won't work for me.

                            However, I can use posix API pthread_create. This goes back to the loop. If I replace std::thread with pthread_create in the example you have provided, I arrive at my old example (in the top of this conversation)

                            One eye opener, which I have got in your example is pthread_join

                            In my example, I was using pthread_exit which is absolutely not accepted to terminate the calling thread, in my case it was a main thread. It was a blunder.

                            Instead of that, now I have updated my code to call pthread_join. This works charm. I am able to bring down the CPU to a least number. This was an outcome of my basic testing. I will continue to perform various tests further.

                            However, that's a good point on moving my business code from main to the worker thread. I shall think about it.

                            Thanks for all those healthy discussions. I am glad that, I got a chance to discuss a lot with the experts like you!

                            K Offline
                            K Offline
                            kumararajas
                            wrote on 30 May 2016, 11:33 last edited by
                            #13

                            So as suggested, I have updated my code that runs UI in the main thread and gets blocked. And, I have worker thread that performs some of business logics.

                            It did not matter to me when I ran the UI in a worker thread. However, I opted to change my way, because of experts suggestions.

                            Thank you all!

                            --Kumara

                            --Kumar

                            1 Reply Last reply
                            0

                            1/13

                            20 May 2016, 12:34

                            • Login

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