Need more help with C++ code syntax - QTConncurent and template
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
class QFuture<void>' has no member named 'result'
You seem to use a
QFuture<void>
which has no result. In order to get any result from yourQFutureWatcher
'sQFuture
, you need to set a type.Like
QVector<T>
( ->QFuture<T>
)See here:
-
"Void" future, just the function is running with
QtConcurrent:run
, no return type.
(https://doc.qt.io/qt-5/qtconcurrentrun.html#passing-arguments-to-the-function) -
QFuture
is from typeQFuture<QString>
because the function, that runs inQtConcurrent:run
is returning aQString
(https://doc.qt.io/qt-5/qtconcurrentrun.html#returning-values-from-the-function)
So check your
QFutureWatcher
and yourQFuture
setup.Edit:
If this
QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
is your function, your
QFuture
shouldn't be<void>
. Does your function actually return aQVector<QStringList>
/QStringList
?@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
class QFuture<void>' has no member named 'result'
You seem to use a
QFuture<void>
which has no result. In order to get any result from yourQFutureWatcher
'sQFuture
, you need to set a type.Like
QVector<T>
( ->QFuture<T>
)See here:
-
"Void" future, just the function is running with
QtConcurrent:run
, no return type.
(https://doc.qt.io/qt-5/qtconcurrentrun.html#passing-arguments-to-the-function) -
QFuture
is from typeQFuture<QString>
because the function, that runs inQtConcurrent:run
is returning aQString
(https://doc.qt.io/qt-5/qtconcurrentrun.html#returning-values-from-the-function)
So check your
QFutureWatcher
and yourQFuture
setup.Edit:
If this
QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
is your function, your
QFuture
shouldn't be<void>
. Does your function actually return aQVector<QStringList>
/QStringList
?Seems that the discussion is back what I originally asked for help with
what is the correct syntax
to retrieve the data from "run " function " for further processing.
Yes, I did not clearly specify if each part is defined with correct types.BTW at this point it is immaterial if the "run:function" actually returns anything - I need to have correct syntax and return types first.
.
I'll recheck my definitions to make sure it is correct. -
-
@JKSH said in Need more help with C++ code syntax - QTConncurent and template:
QVector<QStringList> returnValue = futureWatcher.future().result();
Still no go.
/media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:402: error: 'class QFuture<void>' has no member named 'result' QVector<QStringList> returnValue = futureWatcher.future().result(); ^
More..
Adding
CONFIG += C++11creates havoc with QT examples where "nullptr" is used . Hence I have a choice to rebuild the entire application and undefine "nullptr".
No thanks at this point - to late in the game.PS
Thanks for the history lesson, however "auto" was introduced to C much . much earlier...@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
error: 'class QFuture<void>' has no member named 'result'
QFutureWatcher<void>
does not expect a result (as implied by thevoid
), hence the error.Use
QFutureWatcher<QVector<QStringList>>
instead. (Also, double-check that HCI_Scan_Scan() indeed returns QVector<QStringList>)@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
If this
QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
is your function, your
QFuture
shouldn't be<void>
. Does your function actually return aQVector<QStringList>
/QStringList
?A
QFutureWatcher<void>
can watch anyQFuture<T>
. However,QFutureWatcher<void>::future()
returnsQFuture<void>
, not the originalQFuture<T>
. -
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
error: 'class QFuture<void>' has no member named 'result'
QFutureWatcher<void>
does not expect a result (as implied by thevoid
), hence the error.Use
QFutureWatcher<QVector<QStringList>>
instead. (Also, double-check that HCI_Scan_Scan() indeed returns QVector<QStringList>)@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
If this
QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
is your function, your
QFuture
shouldn't be<void>
. Does your function actually return aQVector<QStringList>
/QStringList
?A
QFutureWatcher<void>
can watch anyQFuture<T>
. However,QFutureWatcher<void>::future()
returnsQFuture<void>
, not the originalQFuture<T>
.@JKSH said in Need more help with C++ code syntax - QTConncurent and template:
However, QFutureWatcher<void>::future() returns QFuture<void>, not the original QFuture<T>.
Yes, that's what I wanted to say there :)
So
future().result()
on aQFuture<void>
shouldn't return herQStringList
orQStringList
-vector, but I cant see where the<void>
is coming from?! Must be aQFutureWatcher<void>
somewhere in the code, where we cant see it? -
@JKSH said in Need more help with C++ code syntax - QTConncurent and template:
However, QFutureWatcher<void>::future() returns QFuture<void>, not the original QFuture<T>.
Yes, that's what I wanted to say there :)
So
future().result()
on aQFuture<void>
shouldn't return herQStringList
orQStringList
-vector, but I cant see where the<void>
is coming from?! Must be aQFutureWatcher<void>
somewhere in the code, where we cant see it?@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
I cant see where the
<void>
is coming from?! Must be aQFutureWatcher<void>
somewhere in the code, where we cant see it?@AnneRanch's original post contains a variable named
futureWatcher
but it didn't show the type declaration. Judging from the error message, the declaration must have beenQFutureWatcher<void> futureWatcher;
That just needs to change to
QFutureWatcher<QVector<QStringList>> futureWatcher;
-
@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
I cant see where the
<void>
is coming from?! Must be aQFutureWatcher<void>
somewhere in the code, where we cant see it?@AnneRanch's original post contains a variable named
futureWatcher
but it didn't show the type declaration. Judging from the error message, the declaration must have beenQFutureWatcher<void> futureWatcher;
That just needs to change to
QFutureWatcher<QVector<QStringList>> futureWatcher;
Found it :)
QFutureWatcher<void> is specialized to not contain any of the result fetching functions. Any QFuture<T> can be watched by a QFutureWatcher<void> as well. This is useful if only status or progress information is needed; not the actual result data.
See also QFuture and Qt Concurrent.
(https://doc.qt.io/qt-5/qfuturewatcher.html#details)
@AnneRanch
If you have a
<void>
type somewhere, you can't work with the result. -
FYI
After changing this// this is wrong // QFutureWatcher<void> futureWatcher; #ifdef BYPASS /media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:275: error: '>>' should be '> >' within a nested template argument list QFutureWatcher<QVector<QStringList>> futureWatcher; ^ #endif QFutureWatcher<QVector<QStringList> > futureWatcher;
The "run" function works as expected, however , the supporting QConcurrent " 1 seconds ticks" needs work.
qDebug()<< "test apply delay function spin to each vector setup map "; // test map vector array with spin function futureWatcher.setFuture(QtConcurrent::map(vector, spin));
/media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:465: error: no matching function for call to 'QFutureWatcher<QVector<QStringList> >::setFuture(QFuture<void>)' futureWatcher.setFuture(QtConcurrent::map(vector, spin)); ^
I'll try to fix that myself...
Appreciate all the help , it has been revealing how things can get complex if one does not pay attentions to ALL PARTS of the code.
-
FYI
After changing this// this is wrong // QFutureWatcher<void> futureWatcher; #ifdef BYPASS /media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:275: error: '>>' should be '> >' within a nested template argument list QFutureWatcher<QVector<QStringList>> futureWatcher; ^ #endif QFutureWatcher<QVector<QStringList> > futureWatcher;
The "run" function works as expected, however , the supporting QConcurrent " 1 seconds ticks" needs work.
qDebug()<< "test apply delay function spin to each vector setup map "; // test map vector array with spin function futureWatcher.setFuture(QtConcurrent::map(vector, spin));
/media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:465: error: no matching function for call to 'QFutureWatcher<QVector<QStringList> >::setFuture(QFuture<void>)' futureWatcher.setFuture(QtConcurrent::map(vector, spin)); ^
I'll try to fix that myself...
Appreciate all the help , it has been revealing how things can get complex if one does not pay attentions to ALL PARTS of the code.
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
The "run" function works as expected, however , the supporting QConcurrent " 1 seconds ticks" needs work.
Yes, because now you cant use your changed
futureWatcher
the same way as used by the Qt Example.
(spin
function doesn't return aQStringList
vector) -
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
The "run" function works as expected, however , the supporting QConcurrent " 1 seconds ticks" needs work.
Yes, because now you cant use your changed
futureWatcher
the same way as used by the Qt Example.
(spin
function doesn't return aQStringList
vector)@Pl45m4
Yes, I realized that. But I hacked it , at lest for now , by defining another
QFutureWatcherQFutureWatcher<QVector<QStringList> > futureWatcher_run; // 1 seconds tick // keep curent SIGNAL / SLOT QFutureWatcher<void> futureWatcher; // keep for SIGNAL etc 1 second ticks
Now as I suspected - I have lost the "concurrency" - the "run" , as coded , blocks process and I have no "concurrent" 1 second ticks running in QProgressDialog.
More fun work.... perhaps just checking for "result" AFTER the "concurrent " is done will work. QProgressDialog sits on top on the area which eventually will show the results , so no hurry until it is gone from view. -
I need to discuss / clarify ONE more "problem" .
I hope I can explain "the problem" using my interpretations of Qt documentation. It is somewhat dupe of what I have said / posted before.
My "primary objective" was to utilize / write multi threaded code to account for a function which takes abut 10 seconds to execute .
I am using "QtConcurrent "framework " which does support multi threading .
I do "QtConcurrent::run" to run time consuming function in ONE thread AND futureWatcher.setFuture(QtConcurrent::map(vector, spin)); in additional FOUR threads.
As is - It all works as expected.The "time consuming function" retrieves data for further processing.
I have a lengthy discussion elsewhere about how to pass / retrieve such data for such processing and it DOES work using following code:QVector<QStringList> returnValue = futureWatcher_run.future().result();
The problem is , as far as I can identify it - the futureWatcher_run.future().result() no longer "runs " as multi threaded / QtConcurrent framework - it appears to run in main thread and is blocking.
Am I wrong ?
I do not have code implemented to actually see / debug the thread execution of the above code.
I do realize my problem is harder to visualize without full code, but how can I verify / change the "returnValue" code to make sure it runs in QtConcurrent framework and in its OWN thread , and not to be blocking?
QStringList *stringList = new QStringList(); // temporary pass QStringList QElapsedTimer timerHCI; timerHCI.start(); futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)); // test returnValue int returnValueIndex = 0; int returnValueSize = 0; qDebug()<< "futureWatcher.setFuture(QtConcurrent::run(HCI, " "&HCI_Scan_Dialog::HCI_Scan_Scan,stringList)) elapsed time " << timerHCI.elapsed() ; #ifdef BYPASS // takes real time QVector<QStringList> returnValue = futureWatcher_run.future().result();
-
I need to discuss / clarify ONE more "problem" .
I hope I can explain "the problem" using my interpretations of Qt documentation. It is somewhat dupe of what I have said / posted before.
My "primary objective" was to utilize / write multi threaded code to account for a function which takes abut 10 seconds to execute .
I am using "QtConcurrent "framework " which does support multi threading .
I do "QtConcurrent::run" to run time consuming function in ONE thread AND futureWatcher.setFuture(QtConcurrent::map(vector, spin)); in additional FOUR threads.
As is - It all works as expected.The "time consuming function" retrieves data for further processing.
I have a lengthy discussion elsewhere about how to pass / retrieve such data for such processing and it DOES work using following code:QVector<QStringList> returnValue = futureWatcher_run.future().result();
The problem is , as far as I can identify it - the futureWatcher_run.future().result() no longer "runs " as multi threaded / QtConcurrent framework - it appears to run in main thread and is blocking.
Am I wrong ?
I do not have code implemented to actually see / debug the thread execution of the above code.
I do realize my problem is harder to visualize without full code, but how can I verify / change the "returnValue" code to make sure it runs in QtConcurrent framework and in its OWN thread , and not to be blocking?
QStringList *stringList = new QStringList(); // temporary pass QStringList QElapsedTimer timerHCI; timerHCI.start(); futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)); // test returnValue int returnValueIndex = 0; int returnValueSize = 0; qDebug()<< "futureWatcher.setFuture(QtConcurrent::run(HCI, " "&HCI_Scan_Dialog::HCI_Scan_Scan,stringList)) elapsed time " << timerHCI.elapsed() ; #ifdef BYPASS // takes real time QVector<QStringList> returnValue = futureWatcher_run.future().result();
@AnneRanch I' don't quite understand your situation, why do you think its not running in its own thread?
Any way, if you want to, take a look at my git repo
https://github.com/DeiVadder/QtThreadExampleIn that I have a project that covers all Qt ways of parallel processing, Related functions are number form 1 to 5.
Qt Concurrent is the number 4
-
@AnneRanch I' don't quite understand your situation, why do you think its not running in its own thread?
Any way, if you want to, take a look at my git repo
https://github.com/DeiVadder/QtThreadExampleIn that I have a project that covers all Qt ways of parallel processing, Related functions are number form 1 to 5.
Qt Concurrent is the number 4
@J-Hilk said in Need more help with C++ code syntax - QTConncurent and template:
@AnneRanch I' don't quite understand your situation, why do you think its not running in its own thread?
Actually - that is silly for me to say.
Of course it is running in its own thread, problem is it is NOT QtConcurrent - one of he expected multi threads .
But I cannot simply prove it - the "debug" is getting too complicated.
I know for sure it is blocking - it is causing the main window to "go gray".
That is from my initial experience - when I was not running QtConcurrent correctly - the main window would turn gray at completion of the function.I'll take a look at your code.
thanks.Any way, if you want to, take a look at my git repo
https://github.com/DeiVadder/QtThreadExampleIn that I have a project that covers all Qt ways of parallel processing, Related functions are number form 1 to 5.
Qt Concurrent is the number 4
-
FYI
After changing this// this is wrong // QFutureWatcher<void> futureWatcher; #ifdef BYPASS /media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:275: error: '>>' should be '> >' within a nested template argument list QFutureWatcher<QVector<QStringList>> futureWatcher; ^ #endif QFutureWatcher<QVector<QStringList> > futureWatcher;
The "run" function works as expected, however , the supporting QConcurrent " 1 seconds ticks" needs work.
qDebug()<< "test apply delay function spin to each vector setup map "; // test map vector array with spin function futureWatcher.setFuture(QtConcurrent::map(vector, spin));
/media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:465: error: no matching function for call to 'QFutureWatcher<QVector<QStringList> >::setFuture(QFuture<void>)' futureWatcher.setFuture(QtConcurrent::map(vector, spin)); ^
I'll try to fix that myself...
Appreciate all the help , it has been revealing how things can get complex if one does not pay attentions to ALL PARTS of the code.
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
Appreciate all the help , it has been revealing how things can get complex if one does not pay attentions to ALL PARTS of the code.
You're welcome. Indeed, complexity tends to grow exponentially.
futureWatcher.setFuture(QtConcurrent::map(vector, spin));
You started this thread by asking about
QtConcurrent::run()
, and now you're addingQtConcurrent::map()
to the mix. These two functions are very different.Let's step back a bit. First, please describe in your own words:
- What does
QtConcurrent::run()
do? What does it return? - What does
QtConcurrent::map()
do? What does it return?
perhaps just checking for "result" AFTER the "concurrent " is done will work.
Yes, you should do this.
The reason for the "block" is documented at https://doc.qt.io/qt-5/qfuture.html#result
- What does
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
Appreciate all the help , it has been revealing how things can get complex if one does not pay attentions to ALL PARTS of the code.
You're welcome. Indeed, complexity tends to grow exponentially.
futureWatcher.setFuture(QtConcurrent::map(vector, spin));
You started this thread by asking about
QtConcurrent::run()
, and now you're addingQtConcurrent::map()
to the mix. These two functions are very different.Let's step back a bit. First, please describe in your own words:
- What does
QtConcurrent::run()
do? What does it return? - What does
QtConcurrent::map()
do? What does it return?
perhaps just checking for "result" AFTER the "concurrent " is done will work.
Yes, you should do this.
The reason for the "block" is documented at https://doc.qt.io/qt-5/qfuture.html#result
@JKSH said in Need more help with C++ code syntax - QTConncurent and template:
- What does
QtConcurrent::run()
do? What does it return?
I "runs" time consuming function " which scans (HCI inquiry) for nearby bluetooth devices and returns their address and name.
- What does
QtConcurrent::map()
do? What does it return?
It "runs" QProgressDialog and updates its "progress bar" in roughly 1 second intervals . The interval is not important.
Thanks to QConcurrent these functions run in multiple threads , hence in 'parallel fashion " as far as the user is concerned.
perhaps just checking for "result" AFTER the "concurrent " is done will work.
Yes, you should do this.
The reason for the "block" is documented at https://doc.qt.io/qt-5/qfuture.html#result
I'll check that.
In the mean time - for entertainment purposes - here is somewhat sanitized version of basic code - the "result" code is still under construction.
{ # ifdef TRACE qDebug() << "QDEBUG TRACE START initialize time consuming task"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; //qDebug()<<"TEMPORARY EXIT "; // return;#ifdef BYPASS #endif qDebug() << " SETUP declare / define (?) consuming function QFutureWatcher<QVector<QStringList> > futureWatcher_run;"; QFutureWatcher<QVector<QStringList> > futureWatcher_run; qDebug() << " SETUP declare / define (?) QFutureWatcher<void> futureWatcher;1 second ticks"; QFutureWatcher<void> futureWatcher; // keep for SIGNAL etc 1 second ticks qDebug() << "SETUP # of iterations as vector array "; QVector<int> vector; //NOTE for now - # of iterations 3*4* estimated number of devices //TODO something smarter - use "finished" SIGNAL int iterations = 35; // temp MN for (int i = 0; i < iterations; ++i) { // first vector cSTART initialize time consuming taskontains time consuming function - no delay // rest of them - single delay time (1 S) #ifdef PROCESS //qDebug()<<" interations loop ?? index " << i; qDebug()<<" vector.append(i) index " << i; // LOOP "; // another delay "iterations //qDebug()<<" another delay iterations (?) "; #endif vector.append(i); } qDebug()<<"SETUP Create QProgressDialog dialog - set paramaters "; // this is a default QProgressDialog constructor QProgressDialog dialog; // QProgressDialog(const QString & labelText, // const QString & cancelButtonText, int minimum, int maximum, // QWidget * parent = 0, Qt::WindowFlags f = 0) #ifdef BYPASS QProgressDialog dialog ( "TEST window title ", " BUTTON text", 0, iterations ,0 ,0); //BUG did not set to TEST window title here // dialog.setWindowModality(Qt::WindowModal); #endif // dialog.labelText(" what is label ?" ); no matching function ?? dialog.setWindowTitle("TEST window title "); dialog.setFixedWidth(500); //W.setWindowTitle("TEST window title "); // set defaulrs of what ??? // dialog.setMaximum(100); // dialog.setRange(10, 1000 ); // If set to 0, the dialog is always shown as soon as any progress is set. // The default is 4000 milliseconds. // int minimumDuration() const // void setMinimumDuration(int ms) dialog.setMinimumDuration(0); // sets delay time to ~ 5 seconds dialog.setRange(0,0); // single shot label only //dialog.show(); //This is done querying the number of processor cores //NOTE won;t work unitil what is done ??? qDebug()<< "SETUP test timer"; QElapsedTimer timer; timer.start(); #ifdef BYPASS //TODO later dialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed())); dialog.show(); // test show #endif qDebug()<<"SETUP ALL connect function futureWatcher and dialog connect SIGNAL SLOT "; // # of iterations ?? " << iterations ; // vector.append(i) LOOP "; qDebug()<<"SETUP setup future WatcherSIGNAL(finished()"; // Resets the progress dialog. The progress dialog becomes hidden if autoClose() is true. //QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); // reset to what ?? qDebug()<<"SETUP setup dialog, SIGNAL(canceled()"; //QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); // TOK // how to emulate these ?? QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); // add tracking slot //QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), this , SLOT(setValue(int))); // create test SLOT to monitor progressValueChanged(int) qDebug() << "SETUP ! create test SLOT to monitor progressValueChanged(int)"; QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), this, SLOT(on_doTaskButton_2_clicked())); // QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)),this, SLOT(on_doTaskButton_3_clicked())); QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)),this, SLOT(on_doTaskButton_3_clicked())); // create test SLOT to monitor progressValueChanged(int) qDebug() << "SETUP create test SLOT to monitor progressValueChanged(int)"; QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), this, SLOT(on_doTaskButton_2_clicked())); // &dialog.getValue()))); qDebug() << "SETUP HCI_Scan_Dialog *HCI = new HCI_Scan_Dialog () with HCI_Scan_Scan function "; HCI_Scan_Dialog *HCI = new HCI_Scan_Dialog (); // run HCI_Scan_scan with QStringList array as parameter qDebug() << "RUN futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList));"; QStringList *stringList = new QStringList(); // temporary pass empty QStringList QElapsedTimer timerHCI; timerHCI.start(); // takes no real time - but HCI_Scan_scan does ! futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)); qDebug() << "CZECH futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList));"; qDebug() << "CZECH futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)) elapsed time " << timerHCI.elapsed() << " mS" ; // NOTE no progress dialog here , no main window gray either // TODO get real thread ID here qDebug() << "RUN futureWatcher.setFuture(QtConcurrent::map(vector, spin));"; futureWatcher.setFuture(QtConcurrent::map(vector, spin)); The reason for the "block" is documented at https://doc.qt.io/qt-5/qfuture.html#result // test real duration of dialog here qDebug() << "RUN dialog.exec(); // run modal dialog;"; QElapsedTimer timer_wait; timer_wait.start(); // futureWatcher.progressValue() qDebug()<<"TODO ?? futureWatcher.progressValue() " << futureWatcher.progressValue(); // what is this for ?? dialog.exec(); // run modal dialog qDebug()<< "futureWatcher.setFuture(QtConcurrent::run(HCI, " "&HCI_Scan_Dialog::HCI_Scan_Scan,stringList)) elapsed time " << timer_wait.elapsed() ; }
PLEASE NOTE
The reason for the "block" is documented at https://doc.qt.io/qt-5/qfuture.html#result
Unfortunately to mitigate this "blocking / waiting for ANY ( first?) result " , which in my case takes 10 seconds - the "result" code , as suggested , cannot be simply placed willy-nilly .
It is back to "emit" SIGNAL or wait until "finished" SIGNAL is emitted.
I am already setup to emit "single device found" SIGNAL from the function itself, not from the "QConcurretn code ".It will take some care and time to add all the necessary emits , SIGNAL SLOT....
Thanks for all the forum help I am making some (slow) progress.
- What does
-
Posting this has given me an idea to take a different approach
What does QtConcurrent::run() do? What does it return?
I "runs" time consuming function " which scans (HCI inquiry) for nearby bluetooth devices and returns their address and name.
What does QtConcurrent::map() do? What does it return?
It "runs" QProgressDialog and updates its "progress bar" in roughly 1 second intervals . The interval is not important.
Naturally - I have been coding these (two main ) tasks sequentially , with emphasis on the QtConncurent " functions" - mainly what they do. What I have missed is "block" approach which is little different that just " function returns..." when coding in event driven environment.
I will try to rebuild the code using this "block" philosophy , maybe it will make the code interaction easier to see.
Here is my goal in pseudo-code{// QtConcurrent block START {# QtConcurrent::run() block code {#QtConcurrent::run() block {# QtConcurrent::map() block {# setup spin vector array block code .. {# setup spin vector array block code {# QtConcurrent::map() block code }// QtConcurrent block END Of course that still does not help to figure out how to process "the time consuming function results / return". What is puzzling - QtConcurennt is multi threading framework and by (my) definition one of the advantages of multi threading is NOT to have blocking processes. So why is "result" blocking ? (I still cannot prove it, I have no "get actual thread ID" code , but it appears to "run" in main process thread and if it blocks that thread - no good. ) Is it not part of the QtConcurrent framework ?
-
Posting this has given me an idea to take a different approach
What does QtConcurrent::run() do? What does it return?
I "runs" time consuming function " which scans (HCI inquiry) for nearby bluetooth devices and returns their address and name.
What does QtConcurrent::map() do? What does it return?
It "runs" QProgressDialog and updates its "progress bar" in roughly 1 second intervals . The interval is not important.
Naturally - I have been coding these (two main ) tasks sequentially , with emphasis on the QtConncurent " functions" - mainly what they do. What I have missed is "block" approach which is little different that just " function returns..." when coding in event driven environment.
I will try to rebuild the code using this "block" philosophy , maybe it will make the code interaction easier to see.
Here is my goal in pseudo-code{// QtConcurrent block START {# QtConcurrent::run() block code {#QtConcurrent::run() block {# QtConcurrent::map() block {# setup spin vector array block code .. {# setup spin vector array block code {# QtConcurrent::map() block code }// QtConcurrent block END Of course that still does not help to figure out how to process "the time consuming function results / return". What is puzzling - QtConcurennt is multi threading framework and by (my) definition one of the advantages of multi threading is NOT to have blocking processes. So why is "result" blocking ? (I still cannot prove it, I have no "get actual thread ID" code , but it appears to "run" in main process thread and if it blocks that thread - no good. ) Is it not part of the QtConcurrent framework ?
@AnneRanch
result()
is blocking the main thread, because you want to use the result there. If the result is not ready, it would not make any sense to continue with the code. Every use ofresult
data would be invalid. So it waits until there is a result, then, for example assigns it to your local variable and continues.
Same aswaitForFinished()
, with the only difference that you don't care about the returned values, when using this.The calculation of your
result
happens in multiple threads concurrently, but the calling thread (your main thread), where you want to use the result, has to wait. -
@AnneRanch
result()
is blocking the main thread, because you want to use the result there. If the result is not ready, it would not make any sense to continue with the code. Every use ofresult
data would be invalid. So it waits until there is a result, then, for example assigns it to your local variable and continues.
Same aswaitForFinished()
, with the only difference that you don't care about the returned values, when using this.The calculation of your
result
happens in multiple threads concurrently, but the calling thread (your main thread), where you want to use the result, has to wait.@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
@AnneRanch
result()
is blocking the main thread, because you want to use the result there. If the result is not ready, it would not make any sense to continue with the code. Every use ofresult
data would be invalid. So it waits until there is a result, then, for example assigns it to your local variable and continues.
Same aswaitForFinished()
, with the only difference that you don't care about the returned values, when using this.The calculation of your
result
happens in multiple threads concurrently, but the calling thread (your main thread), where you want to use the result, has to wait.I do understand that, however , where is the advantage of QtConcurrent then?
Either way , I still do not see "the connection / advantage " between plain function "return" , or processing the pointer passed to the function and this "result" .
Irregardless which way I access the data - it is not what I expect.
I need to "code it" differently.I am already using the "map" letting "connect" do simple updating of progress bar, so why not utilize same method to keep "run" from screwing things up "waiting" for result ? I am using wrong method and in wrong place to boot.
The way I have it now - the "spin" is finished first and when it is finished - I should be able to see if "run" is also finished and then get "result" without any blocking.
-
@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
@AnneRanch
result()
is blocking the main thread, because you want to use the result there. If the result is not ready, it would not make any sense to continue with the code. Every use ofresult
data would be invalid. So it waits until there is a result, then, for example assigns it to your local variable and continues.
Same aswaitForFinished()
, with the only difference that you don't care about the returned values, when using this.The calculation of your
result
happens in multiple threads concurrently, but the calling thread (your main thread), where you want to use the result, has to wait.I do understand that, however , where is the advantage of QtConcurrent then?
Either way , I still do not see "the connection / advantage " between plain function "return" , or processing the pointer passed to the function and this "result" .
Irregardless which way I access the data - it is not what I expect.
I need to "code it" differently.I am already using the "map" letting "connect" do simple updating of progress bar, so why not utilize same method to keep "run" from screwing things up "waiting" for result ? I am using wrong method and in wrong place to boot.
The way I have it now - the "spin" is finished first and when it is finished - I should be able to see if "run" is also finished and then get "result" without any blocking.
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
I am already using the "map" letting "connect" do simple updating of progress bar, so why not utilize same method to keep "run" from screwing things up "waiting" for result ?
QtConcurrent::run()
runs your time-consuming function in another thread. When it finishes, your QFutureWatcher emits thefinished()
signal. Connect this signal to a slot; fetch the result in that slot.What does QtConcurrent::map() do? What does it return?
It "runs" QProgressDialog and updates its "progress bar" in roughly 1 second intervals . The interval is not important.
QtConcurrent::map()
takes a function and a vector that contains N elements. It runs that function N times -- once per vector element. On a modern CPU, multiple copes of that function can run concurrently (in parallel). -
I am hoping this is my LAST post in this thread.
Even after I double check completion of the "time consuming function"
the "returnValue" takes over 1 second to complete.First returnValue QVector<QStringList> = futureWatcher_run.future().result() elapsed time 1533 [mS]
And I really do not want to know why...
Cheers
EDIT / SOLVED
It takes 1.5 seconds to output the DEBUG message ! DUH !
QElapsedTimer timerHCI; timerHCI.start(); QVector<QStringList> returnValue = futureWatcher_run.future().result(); // should take no significant time qDebug()<< "time " << timerHCI.elapsed() ; now the time = ZERO !
-
I am hoping this is my LAST post in this thread.
Even after I double check completion of the "time consuming function"
the "returnValue" takes over 1 second to complete.First returnValue QVector<QStringList> = futureWatcher_run.future().result() elapsed time 1533 [mS]
And I really do not want to know why...
Cheers
EDIT / SOLVED
It takes 1.5 seconds to output the DEBUG message ! DUH !
QElapsedTimer timerHCI; timerHCI.start(); QVector<QStringList> returnValue = futureWatcher_run.future().result(); // should take no significant time qDebug()<< "time " << timerHCI.elapsed() ; now the time = ZERO !
@AnneRanch
It will not take 1.5 seconds to executeqDebug()<< "time " << timerHCI.elapsed()
. However, it may well take 1.5 seconds to get the return result back fromfutureWatcher_run.future().result()
, if that's how long it takes to complete all of the threads. -
@Pl45m4 said in Need more help with C++ code syntax - QTConncurent and template:
@AnneRanch
result()
is blocking the main thread, because you want to use the result there. If the result is not ready, it would not make any sense to continue with the code. Every use ofresult
data would be invalid. So it waits until there is a result, then, for example assigns it to your local variable and continues.
Same aswaitForFinished()
, with the only difference that you don't care about the returned values, when using this.The calculation of your
result
happens in multiple threads concurrently, but the calling thread (your main thread), where you want to use the result, has to wait.I do understand that, however , where is the advantage of QtConcurrent then?
Either way , I still do not see "the connection / advantage " between plain function "return" , or processing the pointer passed to the function and this "result" .
Irregardless which way I access the data - it is not what I expect.
I need to "code it" differently.I am already using the "map" letting "connect" do simple updating of progress bar, so why not utilize same method to keep "run" from screwing things up "waiting" for result ? I am using wrong method and in wrong place to boot.
The way I have it now - the "spin" is finished first and when it is finished - I should be able to see if "run" is also finished and then get "result" without any blocking.
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
I do understand that, however , where is the advantage of QtConcurrent then?
There are two different use cases of
QtConcurrent
: 1) Similar to what you are doing you can launch multiple tasks in separate runs one after the other and only after all the runs callresult()
. This would mean that you can compute several tasks in parallel, but it also means that you have a synchronization point when you want to access the results. Furthermore, if you run a whole bunch of tasks usingQtConcurrent
it will use a thread pool in the background such that your CPU cores are not oversubscribed. This is the main advantage overQThread
. 2) The other use case, as already meantioned, is to only callrun
in your function and connect thefinished
signals of theQFutureWatcher
to a separate slot which will continue from where you want to access the results. Basically, this means that you need to split your function right there where you callresult()
(and you don't have to call result anymore because it will be the parameter of your function).Furthermore,
map
andmapReduce
automatically parallelize and call your function on each element. This is the really helpful part ofQtConcurrent
.One quick fix to your problem (I haven't made up my mind if this is good or bad design) would be to run your existing function inside a separate thread. Then your separate thread would block instead of the main thread. However, this only works if you don't do any GUI stuff inside this thread. This would work something like this:
QThread::create([=]() { // your whole function code here... ... futureWatcher_run.setFuture(QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)); .... QVector<QStringList> returnValue = futureWatcher_run.future().result(); // now this will block })->start();