Solved QThread + Shared Library
-
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.
-
@fem_dev
Hi,
about QThread I suggest you to readhttps://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
-
@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 usageQThread
reference version is Qt 4.7.
I know that theconnect()
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 5QThread
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 thethread->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 theprocess()
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? -
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#startYou 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 -
@CP71 Thank you so much! You are great!
-
@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!
-
@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#waitAnyway, 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! -
@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
andslots
(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. -
@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
-
-
@fem_dev
The same to you!