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 + Shared Library
Forum Updated to NodeBB v4.3 + New Features

QThread + Shared Library

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 3 Posters 1.2k 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi,

    @fem_dev said in QThread + Shared Library:

    When the main application calls the plugin::run() method, it will be started in a new thread....and when the run() method finish, this new thread is completly finished and quit?"

    The run implementation you describe, unless I misunderstood, is a blocking call that will freeze your main thread the same way you would by not using a thread.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    0
    • F fem_dev

      I'm studing QThread and I already wrote some simple examples, but I'm having problems to use the same logic to my real application.

      Today I have a C++ Qt 5 GUI Main Application that loads a collection of "plugins" (shared libraries) in run-time.
      This plugins were written in C++ Qt too.

      All plugins are written in with the same C++ structure:

      • Plugin_API.h (Interface - Virtual methods)
      • Plugin.h (Just overwrite the Interface methods)
      • Plugin.cpp (Implementation)

      Here is the Plugin_API.h

      #ifndef PLUGIN_API_H
      #define PLUGIN_API_H
      
      #include <QObject>
      #include <QString>
      #include <QThread>
      
      #include <QDebug>
      
      class Plugin_API : public QObject
      {
          Q_OBJECT
      
      private:
      
      public:
          Plugin_API() 
          {
          }
      
          virtual ~Plugin_API() = default;
          virtual void run() = 0;
      
          // ===== SIGNALS ===== //
      signals:
          void printConsole(const std::string msg);
      };
      
      // Declare our interface:
      Q_DECLARE_INTERFACE(Plugin_API, "com.rotortest.plugin")
      
      #endif // PLUGIN_API_H
      

      Here is the Plugin.h

      #ifndef PLUGIN_H
      #define PLUGIN_H
      
      #include <QObject>
      #include <QtPlugin>
      #include <iostream>
      
      #include "plugin_global.h"
      #include "plugin_api.h"
      
      class PLUGIN_EXPORT Plugin: public Plugin_API
      {
          Q_OBJECT
          Q_PLUGIN_METADATA(IID "com.rotortest.plugin")
          Q_INTERFACES(Plugin_API)
      
      public:
      
          explicit Plugin(QObject* parent = nullptr);
          ~Plugin() override;
      
          void run() override;
      
      private:
      
      public slots:
      
      };
      
      #endif // PLUGIN_H
      

      I load each plugin (file) in a foreach loop using:

      QPluginLoader loader(file);
      if (loader.load()) {
          Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
                 
          // Another stuff...
      }
      

      Finally, after the Main Application load all plugins using QPluginLoader class, I want to run each plugin in a serial order, like this:

      std::vector<Plugin_API*> pluginStack;
      // Fill this vector above...
      
      for(size_t i = 0; i < pluginStack.size(); i++) {
          pluginStack[i]->run();
      }
      

      Now, I can to it just calling the plugin::run() method, but this method takes a long time to run.

      So, I think that will be better to change this code to support QThread to be able to:

      • Unlock the main application GUI
      • Monitor the plugin status in another thread

      I read the Qt 5 documentation link here about the 2 possibilities of QThread implementation:

      • Worker (I can't see how to do it in my case...)
      • Extending the QThread class (I think that is the most close with my problem...but I don't have sure...)

      I did both implementations in a simple example, and it works. But I need some help to implement it in my real case above.
      Could you help me to move this implementation above to a new implementation where:

      "When the main application calls the plugin::run() method, it will be started in a new thread....and when the run() method finish, this new thread is completly finished and quit?"


      Another Youtube tutorial reference:

      • Extending the QThread example: https://www.youtube.com/watch?v=LCIes6xehlA&list=PL2D1942A4688E9D63&index=33
      • Worker example: https://www.youtube.com/watch?v=yazMHbIew0Q&list=PL2D1942A4688E9D63&index=35
      CP71C Offline
      CP71C Offline
      CP71
      wrote on last edited by
      #3

      @fem_dev
      Hi,
      about QThread I suggest you to read

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

      The best way to use Qthread is using Worker.

      Say this, I think could be useful QtConcurrent for your goal.

      Regards

      F 1 Reply Last reply
      2
      • CP71C CP71

        @fem_dev
        Hi,
        about QThread I suggest you to read

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

        The best way to use Qthread is using Worker.

        Say this, I think could be useful QtConcurrent for your goal.

        Regards

        F Offline
        F Offline
        fem_dev
        wrote on last edited by
        #4

        @CP71 Thank you...

        I changed my code using this tutorial above and it work well! Thank you.

        Here is my adapted source-code that runs inside my main application:

        for (size_t step_id = 0; step_id < numSteps; step_id++) {
            QThread* thread = new QThread;
            pluginStack[step_id]->moveToThread(thread);
            
            connect(pluginStack[step_id], SIGNAL(error(QString)), this, SLOT(handleResults(QString)));
            connect(thread, SIGNAL(started()), pluginStack[step_id], SLOT(process()));
            connect(pluginStack[step_id], SIGNAL(finished()), thread, SLOT(quit()));
            connect(pluginStack[step_id], SIGNAL(finished()), pluginStack[step_id], SLOT(deleteLater()));
            connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        
            thread->setPriority(QThread::HighestPriority); // this line is not working!
            thread->start();
        }
        

        I have 3 questions:

        1- Qt4 vs Qt5
        I saw that this tutorial is from November 2011. And the usage QThread reference version is Qt 4.7.
        I know that the connect() notation has changed in Qt5.
        I would like to know if I need to adapt another things in this code to move from Qt4 to Qt5.
        Looking in the "Worker method" of the Qt 5 QThread documentation here, I think that may be some has need to change...but I don't have sure what or why.

        2- SetPriority() method
        I added just a single line before the thread->start() to set the thread priority. Look the code above.
        But, when I added it, I got this run-time error below:

        QThread::setPriority: Cannot set priority, thread is not running
        

        3- "CPU Usage"
        Here is the process() method that is called when the thread started:

        void Plugin::process()
        {
            qDebug("Start process");
        
            size_t a = 0;
        
            for (size_t i = 0; i < 100; i++) {
                for (size_t j = 0; j < 1000000; j++) {
                    a = i + j;
                }
            }
        
            qDebug() << "End process";
        
            emit finished();
        }
        

        In my CPU Usage Monitor, I have 4 Cores.
        When this plugin is running, I was expecting that one of theses cores should be usage at 100%, but it doesn't happening.
        Why?

        CP71C 1 Reply Last reply
        1
        • F fem_dev

          @CP71 Thank you...

          I changed my code using this tutorial above and it work well! Thank you.

          Here is my adapted source-code that runs inside my main application:

          for (size_t step_id = 0; step_id < numSteps; step_id++) {
              QThread* thread = new QThread;
              pluginStack[step_id]->moveToThread(thread);
              
              connect(pluginStack[step_id], SIGNAL(error(QString)), this, SLOT(handleResults(QString)));
              connect(thread, SIGNAL(started()), pluginStack[step_id], SLOT(process()));
              connect(pluginStack[step_id], SIGNAL(finished()), thread, SLOT(quit()));
              connect(pluginStack[step_id], SIGNAL(finished()), pluginStack[step_id], SLOT(deleteLater()));
              connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
          
              thread->setPriority(QThread::HighestPriority); // this line is not working!
              thread->start();
          }
          

          I have 3 questions:

          1- Qt4 vs Qt5
          I saw that this tutorial is from November 2011. And the usage QThread reference version is Qt 4.7.
          I know that the connect() notation has changed in Qt5.
          I would like to know if I need to adapt another things in this code to move from Qt4 to Qt5.
          Looking in the "Worker method" of the Qt 5 QThread documentation here, I think that may be some has need to change...but I don't have sure what or why.

          2- SetPriority() method
          I added just a single line before the thread->start() to set the thread priority. Look the code above.
          But, when I added it, I got this run-time error below:

          QThread::setPriority: Cannot set priority, thread is not running
          

          3- "CPU Usage"
          Here is the process() method that is called when the thread started:

          void Plugin::process()
          {
              qDebug("Start process");
          
              size_t a = 0;
          
              for (size_t i = 0; i < 100; i++) {
                  for (size_t j = 0; j < 1000000; j++) {
                      a = i + j;
                  }
              }
          
              qDebug() << "End process";
          
              emit finished();
          }
          

          In my CPU Usage Monitor, I have 4 Cores.
          When this plugin is running, I was expecting that one of theses cores should be usage at 100%, but it doesn't happening.
          Why?

          CP71C Offline
          CP71C Offline
          CP71
          wrote on last edited by
          #5

          @fem_dev

          You are welcome!

          1- Qt4 vs Qt5
          About thread Qt4’s code is full compatibility with Qt5, however, one thing you could change: the connect of signals.

          https://wiki.qt.io/New_Signal_Slot_Syntax

          2- SetPriority() method
          Yep, it is normal, read:
          https://doc.qt.io/qt-5/qthread.html#setPriority
          https://doc.qt.io/qt-5/qthread.html#start

          You can write thread→start(QThread::HighestPriority);

          Pay attention at priority, set with carefully.

          https://doc.qt.io/qt-5/qthread.html#Priority-enum

          3- "CPU Usage"
          https://doc.qt.io/qt-5/thread-basics.html

          F 2 Replies Last reply
          4
          • CP71C CP71

            @fem_dev

            You are welcome!

            1- Qt4 vs Qt5
            About thread Qt4’s code is full compatibility with Qt5, however, one thing you could change: the connect of signals.

            https://wiki.qt.io/New_Signal_Slot_Syntax

            2- SetPriority() method
            Yep, it is normal, read:
            https://doc.qt.io/qt-5/qthread.html#setPriority
            https://doc.qt.io/qt-5/qthread.html#start

            You can write thread→start(QThread::HighestPriority);

            Pay attention at priority, set with carefully.

            https://doc.qt.io/qt-5/qthread.html#Priority-enum

            3- "CPU Usage"
            https://doc.qt.io/qt-5/thread-basics.html

            F Offline
            F Offline
            fem_dev
            wrote on last edited by
            #6

            @CP71 Thank you so much! You are great!

            1 Reply Last reply
            1
            • CP71C CP71

              @fem_dev

              You are welcome!

              1- Qt4 vs Qt5
              About thread Qt4’s code is full compatibility with Qt5, however, one thing you could change: the connect of signals.

              https://wiki.qt.io/New_Signal_Slot_Syntax

              2- SetPriority() method
              Yep, it is normal, read:
              https://doc.qt.io/qt-5/qthread.html#setPriority
              https://doc.qt.io/qt-5/qthread.html#start

              You can write thread→start(QThread::HighestPriority);

              Pay attention at priority, set with carefully.

              https://doc.qt.io/qt-5/qthread.html#Priority-enum

              3- "CPU Usage"
              https://doc.qt.io/qt-5/thread-basics.html

              F Offline
              F Offline
              fem_dev
              wrote on last edited by
              #7

              @CP71 my last doubt:

              Here is my new adapted source-code:

              for (size_t step_id = 0; step_id < numSteps; step_id++) {
                  // ===== RUNNING THE PLUGIN ===== //
              
                  QThread* thread = new QThread;
                  pluginStack[step_id]->moveToThread(thread);
                  
                  qRegisterMetaType<std::string>("std::string");
                  connect(pluginStack[step_id],  &Plugin_API::sendMsg, this, &job_manager::handleResults);
                  connect(thread, &QThread::started, pluginStack[step_id], &Plugin_API::process);
                  connect(pluginStack[step_id], &Plugin_API::finished, thread, &QThread::quit);
                  connect(pluginStack[step_id], &Plugin_API::finished, pluginStack[step_id], &Plugin_API::deleteLater);
                  connect(thread, &QThread::finished, thread, &QThread::deleteLater);
              
                  thread->start(QThread::HighestPriority);
              
                  // WAIT UNTIL THIS THREAD FINISH
                  thread->wait(); // Not woking!
              }
              

              When I added this wait() line, my application run the first thread (step_id = 0), but after that, the whole system freezes.

              How can I execute all plugins in a serial sequence?

              Thank you again!

              CP71C 1 Reply Last reply
              0
              • F fem_dev

                @CP71 my last doubt:

                Here is my new adapted source-code:

                for (size_t step_id = 0; step_id < numSteps; step_id++) {
                    // ===== RUNNING THE PLUGIN ===== //
                
                    QThread* thread = new QThread;
                    pluginStack[step_id]->moveToThread(thread);
                    
                    qRegisterMetaType<std::string>("std::string");
                    connect(pluginStack[step_id],  &Plugin_API::sendMsg, this, &job_manager::handleResults);
                    connect(thread, &QThread::started, pluginStack[step_id], &Plugin_API::process);
                    connect(pluginStack[step_id], &Plugin_API::finished, thread, &QThread::quit);
                    connect(pluginStack[step_id], &Plugin_API::finished, pluginStack[step_id], &Plugin_API::deleteLater);
                    connect(thread, &QThread::finished, thread, &QThread::deleteLater);
                
                    thread->start(QThread::HighestPriority);
                
                    // WAIT UNTIL THIS THREAD FINISH
                    thread->wait(); // Not woking!
                }
                

                When I added this wait() line, my application run the first thread (step_id = 0), but after that, the whole system freezes.

                How can I execute all plugins in a serial sequence?

                Thank you again!

                CP71C Offline
                CP71C Offline
                CP71
                wrote on last edited by
                #8

                @fem_dev
                Hi,
                you have set a infinite timeout in wait, check execution of first thread why it has never finished its work
                https://doc.qt.io/qt-5/qthread.html#wait

                Anyway, purpose of threads is to allow processes to run concurrently, if you really need to wait the ending of thread’s working you don’t really need a thread.
                But maybe I don't really understand your goal! ;)

                I don’t know your code or your plugin, but is so heavy to run all threads?

                Let’s suppose I need to do the same thing (run a thread at a time), my approach should be:

                • Run first thread and prossegue with main thread
                • When the thread has finished its job I run the next thread and so on.

                Clearly, every need has its story! ;)
                So maybe the way described above isn’t good for you!

                F 1 Reply Last reply
                0
                • CP71C CP71

                  @fem_dev
                  Hi,
                  you have set a infinite timeout in wait, check execution of first thread why it has never finished its work
                  https://doc.qt.io/qt-5/qthread.html#wait

                  Anyway, purpose of threads is to allow processes to run concurrently, if you really need to wait the ending of thread’s working you don’t really need a thread.
                  But maybe I don't really understand your goal! ;)

                  I don’t know your code or your plugin, but is so heavy to run all threads?

                  Let’s suppose I need to do the same thing (run a thread at a time), my approach should be:

                  • Run first thread and prossegue with main thread
                  • When the thread has finished its job I run the next thread and so on.

                  Clearly, every need has its story! ;)
                  So maybe the way described above isn’t good for you!

                  F Offline
                  F Offline
                  fem_dev
                  wrote on last edited by fem_dev
                  #9

                  @CP71 Thank you for your quick response. I will explain my case better here.

                  I want that my main app can be expanded by any another C++ developer. So each developed extension must be a shared library (plugin) that will be loaded in run-time by the main app.

                  Each plugin is a huge numerical calculation and it can take several hours to finish.

                  Finally, the user open the Main App GUI, set a list of plugins with parameters and click the button "start processing".

                  In my case, the output of the first plugin is the input of the next one.
                  So, I need that the plugin list execution MUST BE in a serial order.

                  I can be wrong, but I was thinking to use the thread approach to get:

                  • No main application GUI freeze
                  • Enable to send and receive signals and slots (from plugin to main app and vice versa)

                  Is there a better solution to this problem?


                  @CP71 said in QThread + Shared Library:

                  Let’s suppose I need to do the same thing (run a thread at a time), my approach should be:

                  • Run first thread and prossegue with main thread
                  • When the thread has finished its job I run the next thread and so on.

                  Yes, but how can I do it? I tried to use wait() but I have to set a timeout. I would like to wait until the thread finish. Just it.

                  CP71C 1 Reply Last reply
                  0
                  • F fem_dev

                    @CP71 Thank you for your quick response. I will explain my case better here.

                    I want that my main app can be expanded by any another C++ developer. So each developed extension must be a shared library (plugin) that will be loaded in run-time by the main app.

                    Each plugin is a huge numerical calculation and it can take several hours to finish.

                    Finally, the user open the Main App GUI, set a list of plugins with parameters and click the button "start processing".

                    In my case, the output of the first plugin is the input of the next one.
                    So, I need that the plugin list execution MUST BE in a serial order.

                    I can be wrong, but I was thinking to use the thread approach to get:

                    • No main application GUI freeze
                    • Enable to send and receive signals and slots (from plugin to main app and vice versa)

                    Is there a better solution to this problem?


                    @CP71 said in QThread + Shared Library:

                    Let’s suppose I need to do the same thing (run a thread at a time), my approach should be:

                    • Run first thread and prossegue with main thread
                    • When the thread has finished its job I run the next thread and so on.

                    Yes, but how can I do it? I tried to use wait() but I have to set a timeout. I would like to wait until the thread finish. Just it.

                    CP71C Offline
                    CP71C Offline
                    CP71
                    wrote on last edited by
                    #10

                    @fem_dev
                    Ok,
                    First you don’t need of wait.
                    I would do what I have already written, I run a thread at a time.
                    To do this I would write a slot in MainWindow or in your core where I manage my plugins loading.

                    I’m not sure Qthread::HighestPriority is a good idea, my first choice would be default priority.

                    Your Init application function
                    {
                    ….
                    step_id = 0; //Member of class
                    loadPlugin(step_id);
                    ….
                    }

                    void MyObject::loadPlugin( int step_id )
                    {
                    QThread* thread = new QThread;
                    pluginStack[step_id]->moveToThread(thread);

                    qRegisterMetaType<std::string>("std::string");
                    connect(pluginStack[step_id],  &Plugin_API::sendMsg, this, &job_manager::handleResults);
                    connect(thread, &QThread::started, pluginStack[step_id], &Plugin_API::process);
                    connect(pluginStack[step_id], &Plugin_API::finished, thread, &QThread::quit);
                    						connect(pluginStack[step_id], &Plugin_API::finished, myMainWindow or myCore, &MyObject::pluginLoaded); //New code
                    connect(pluginStack[step_id], &Plugin_API::finished, pluginStack[step_id], &Plugin_API::deleteLater);
                    connect(thread, &QThread::finished, thread, &QThread::deleteLater);
                    thread->start();
                    

                    }

                    //Here You manage serial plugin loading and possible checking
                    void MyObject::pluginLoaded()
                    {
                    object management and check ...

                    step_id++;
                    loadPlugin(step_id)
                    
                    ...
                    

                    }

                    This is only an example, written at 5:30 AM when I read your post :D

                    There is QthreadPool too, but maybe in this case my first choice are QThreads

                    F 1 Reply Last reply
                    1
                    • CP71C CP71

                      @fem_dev
                      Ok,
                      First you don’t need of wait.
                      I would do what I have already written, I run a thread at a time.
                      To do this I would write a slot in MainWindow or in your core where I manage my plugins loading.

                      I’m not sure Qthread::HighestPriority is a good idea, my first choice would be default priority.

                      Your Init application function
                      {
                      ….
                      step_id = 0; //Member of class
                      loadPlugin(step_id);
                      ….
                      }

                      void MyObject::loadPlugin( int step_id )
                      {
                      QThread* thread = new QThread;
                      pluginStack[step_id]->moveToThread(thread);

                      qRegisterMetaType<std::string>("std::string");
                      connect(pluginStack[step_id],  &Plugin_API::sendMsg, this, &job_manager::handleResults);
                      connect(thread, &QThread::started, pluginStack[step_id], &Plugin_API::process);
                      connect(pluginStack[step_id], &Plugin_API::finished, thread, &QThread::quit);
                      						connect(pluginStack[step_id], &Plugin_API::finished, myMainWindow or myCore, &MyObject::pluginLoaded); //New code
                      connect(pluginStack[step_id], &Plugin_API::finished, pluginStack[step_id], &Plugin_API::deleteLater);
                      connect(thread, &QThread::finished, thread, &QThread::deleteLater);
                      thread->start();
                      

                      }

                      //Here You manage serial plugin loading and possible checking
                      void MyObject::pluginLoaded()
                      {
                      object management and check ...

                      step_id++;
                      loadPlugin(step_id)
                      
                      ...
                      

                      }

                      This is only an example, written at 5:30 AM when I read your post :D

                      There is QthreadPool too, but maybe in this case my first choice are QThreads

                      F Offline
                      F Offline
                      fem_dev
                      wrote on last edited by
                      #11

                      @CP71 Thank you so much for your attention and patience.

                      I understood now!

                      All the best!

                      CP71C 1 Reply Last reply
                      1
                      • F fem_dev

                        @CP71 Thank you so much for your attention and patience.

                        I understood now!

                        All the best!

                        CP71C Offline
                        CP71C Offline
                        CP71
                        wrote on last edited by
                        #12

                        @fem_dev
                        The same to you!

                        1 Reply Last reply
                        0

                        • Login

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