Will this even work - why using QTConcurrent in first place ?
-
I have another discussion going about IMPLEMENTATION of QtConcurrent.
I am posting this not as a dupe , but a question about the concept.QT is a event driven , similar to Windows OS , system.
My task is to implement time consuming function - - up to 30 seconds competition. The function RETURNS a value. Adding such function into slot - activated by "push button" - blocks the slot event loop.
To demonstrate - If I wrap the "time consuming call" in debug prints they do not get executed (!) until the "time consuming call " completes.
QtConcurrent builds new thread and can run the " time consuming function ". It will still take time and the main thread HAS TO WAIT for the " time consuming function " RETURN value.
The main processing thread has to have means to "wait " .
It looks as adding Qt Concurrent is of no help - the main process has to wait OR
Qt Concurrent has to be implemented as "event " running
" time consuming function "
'
Or would implementing "EVENT" without QTConcurrent be simpler ?
( multi-threading in this case is not important - delay is a delay )I am open to suggestions...
-
@AnneRanch said in Will this even work - why using QTConcurrent in first place ?:
It will still take time and the main thread HAS TO WAIT for the " time consuming function " RETURN value.
The main processing thread has to have means to "wait " .No, it has not to wait - use a QFutureWatcher and connect to it's finished signal to get notified when the task is done and you can get the result
-
It seems to be controller-worker case. Controller starts worker by and it is notified by signal from worker when the long operation is finished. During that time it does not have to wait, it does something else.
Taking GUI with button as in your example - when push button is clicked GUI starts the worker and probably disables the button, provides some feedback to user, etc. and when the long operation is done, some GUI slot is activated and GUI shows the result. Meanwhile GUI responds to user inputs. -
The point is that the UI remains responsive while your task processes.
In your case, you can do this by QtConcurrent::run but just as well using QThread or QRunnable.Where QtConcurrent really shines is when you have run a task on multiple items (e.g. you have a CPU-intensive image enhancement algorithm, and want to apply it to 2000 images). There, it's as simple as to create a list of input data, a static function that returns a result, and call QtConcurrent::map (or one of it's friends)...
-
@Christian-Ehrlicher Thank you, I just independently "discovered" QFutureWatcher" too. That will work perfectly.
-
@AnneRanch
@KejPi said in Will this even work - why using QTConcurrent in first place ?:
It seems to be controller-worker case. Controller starts worker by and it is notified by signal from worker when the long operation is finished. During that time it does not have to wait, it does something else.
Well put, however it does not suggest HOW to accomplish the task in QT.
But that was not the intent of this post- to suggest how to implement only to confirm it is feasible.Taking GUI with button as in your example - when push button is clicked GUI starts the worker and probably disables the button, provides some feedback to user, etc. and when the long operation is done, some GUI slot is activated and GUI shows the result. Meanwhile GUI responds to user inputs.
Maybe it would be more technically correct not to use "GUI" but process / thread.
But to idea is same... -
There are a lot of ways to do multithreading in Qt.
I think if you're new(ish) to Qt I wouldn't recommend your approach actually. After several years of using Qt I still fight QtConcurrent approach a little confusing.
I would recommend a moveToThread approach to start off.
It is pretty simple you make a class that will do your work. It has to inherit QObject.
Give it a slot startWork(params)
and a signal finishedWork(results)Assuming your using widgets your main code would look something like this:
#include "mainwindow.h" #include "processingclass.h" #include <QApplication> #include <QThread> int main(int argc, char *argv[]) { QApplication a(argc, argv); ProcessingClass processor; MainWindow w; QThread processingThread; processor.moveToThread(&processingThread); QObject::connect(&processingThread,&QThread::started,&processor,&ProcessingClass ::init); //This may be needed in some cases to instantiate objects in the new thread. There can be issues with some objects when moving the parent into a new thread. QObject::connect(&w,&MainWindow::startWork,&processor,&ProcessingClass ::startWork); QObject::connect(&processor,&ProcessingClass ::finishedWork,&w,&MainWindow::finishedWork); QObject::connect(&a,&QApplication::aboutToQuit,&processingThread,&QThread::quit); //you might have to put more effort into the "quitting part" you are going to want to make sure you handle the case of when your worker is 1/2 way through and someone hits that x button. processingThread.start(); //start up that event loop in the new thread which will be doing your work. w.show(); return a.exec(); }
(Could be typos above I just wrote it in the forums)
I think once you get comfortable with this simple approach you can start looking at more "advanced" Qt classes i.e. like QtConcurrent, QThreadPool, QRunnable etc.
-
@MrShawn said in Will this even work - why using QTConcurrent in first place ?:
There are a lot of ways to do multithreading in Qt.
I think if you're new(ish) to Qt I wouldn't recommend your approach actually. After several years of using Qt I still fight QtConcurrent approach a little confusing.
I would recommend a moveToThread approach to start off.
It is pretty simple you make a class that will do your work. It has to inherit QObject.
Give it a slot startWork(params)
and a signal finishedWork(results)Assuming your using widgets your main code would look something like this:
#include "mainwindow.h" #include "processingclass.h" #include <QApplication> #include <QThread> int main(int argc, char *argv[]) { QApplication a(argc, argv); ProcessingClass processor; MainWindow w; QThread processingThread; processor.moveToThread(&processingThread); QObject::connect(&processingThread,&QThread::started,&processor,&ProcessingClass ::init); //This may be needed in some cases to instantiate objects in the new thread. There can be issues with some objects when moving the parent into a new thread. QObject::connect(&w,&MainWindow::startWork,&processor,&ProcessingClass ::startWork); QObject::connect(&processor,&ProcessingClass ::finishedWork,&w,&MainWindow::finishedWork); QObject::connect(&a,&QApplication::aboutToQuit,&processingThread,&QThread::quit); //you might have to put more effort into the "quitting part" you are going to want to make sure you handle the case of when your worker is 1/2 way through and someone hits that x button. processingThread.start(); //start up that event loop in the new thread which will be doing your work. w.show(); return a.exec(); }
(Could be typos above I just wrote it in the forums)
I think once you get comfortable with this simple approach you can start looking at more "advanced" Qt classes i.e. like QtConcurrent, QThreadPool, QRunnable etc.
All very good and valid points -especially when the intent of THIS post was to evaluate feasibility. .
To be honest , me as an old fart is a believer that there " are many ways to skin a cat...
Unfortunately suggesting alternatives seldom fixes the original problem. , just masks it.
-
@AnneRanch
AnneRanch about 4 hours ago
@MrShawn said in Will this even work - why using QTConcurrent in first place ?:
I have been looking at your suggestion, unfortunately I cannot "reply " again since I did once. So hopefully you will find this.
From academic point of view - I was under the impression that QTConcurrent is a "wrapper" of "low level stuff " - likes thread. As such I expected KISS .
The limits of passing "only" max of 5 parameters was a bad indicator of things to come. My main "complain " is the barrage of nothing saying errors.
It actually started by saying - the results have failed , and said nothing what the possible source of the failing results are.
The QTConcurrent needs QFuture and QFutureWatcher to be useful...
I am not a total idiot - I have been writing code since 1975 , I have done some QA ( for living) and cannot stand " I did not know what it did so I deleted it " Replacing failing code with "better (and more complex) code " is not my idea of troubleshooting.
Enough ranting , it does no good anyway .
I'll try plain "new thread " next...\