Unsolved Need more help with C++ code syntax - QTConncurent and template
-
My QtConcurrent works in principle.
Now for details - again strictly C++ code , not a Qt problem.This is how I define "time consuming function".
For now I pass QStringList to it, not a problem passing QVector later.QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
This is how I implement the function and it works as expected.
QStringList *stringList = new QStringList(); futureWatcher.setFuture( QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList)); qDebug()<< "temporary debug pause "; // wait for completion qDebug()<< "test apply delay function spin to each vector
The "problem" - AFTER the time consuming function completes I need the main thread to continue . And that is where I am stuck .
- QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList) returns QVector <QStringList> and I have no idea how to write the code to access this return value - where ?
futureWatcher.setFuture( **HERE ??** QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList));
- I am thinking to implement "emit" to "switch back" to main process.
Not really sure where it belongs .
I am already monitoring few "time marks" using "emit" SIGNAL .
Or should I just let QtConcurent finish ?
It does "emit" "finished" SIGNAL already.
(still need to access the - QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList) return value - which takes about 10 seconds to get it .Again I am asking for C++ (template / vector) syntax help or suggestions how to continue the main thread AFTER the time consuming function is done.
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
- QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan,stringList) returns QVector <QStringList> and I have no idea how to write the code to access this return value
Actually,
QtConcurrent::run(HCI, &HCI_Scan_Dialog::HCI_Scan_Scan, stringList)
returnsQFuture<QVector<QStringList>>
in your case. Your code already passes this correctly to your QFutureWatcher.The important points are:
- QFuture stores the return value of your function.
- QFutureWatcher stores your QFuture.
So, you can retrieve the return value of HCI_Scan_Scan() by calling
auto returnValue = futureWatcher.future().result()
See
- I am thinking to implement "emit" to "switch back" to main process.
You don't need to implement or emit your own signal. Just connect a slot/function to QFutureWatcher's
finished()
signal. That should automatically run in the main thread after your 10 seconds have elapsed.QVector<QStringList> HCI_Scan_Dialog::HCI_Scan_Scan(QStringList *string_array)
Instead of passing a
QStringList*
as a function parameter, it is good practice to passconst QStringList&
instead. The same idea applies when passing a QVector or any other container. -
@JKSH said in Need more help with C++ code syntax - QTConncurent and template:
auto returnValue = futureWatcher.future().result()
Perhaps I missed something here , but I am getting this error
/media/d/QT/QT_PROJECT_CAT/CAT_V1/configuredialog.cpp:403: error: 'returnValue' does not name a type auto returnValue = futureWatcher.future().result(); ^
Is "auto " type "standard" in Qt or some option I forgot to set ?
I need to read all the links you have posted , but I noticed that " it will block until finished" . If that is the case my usage of QtConcurent is NOT what I expected , but I will know better after I get this "auto " resolved.
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
Is "auto " type "standard" in Qt or some option I forgot to set ?
This has nothing to do with Qt. "auto" is a C++ keyword and was introduced in C++11 if I remember correctly. What compiler do you use (compiler version is also important).
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
Is "auto " type "standard" in Qt or some option I forgot to set ?
auto
is a C++ keyword that asks the compiler to automatically deduce the datatype by looking at the surrounding code. In your case, the following two lines produce exactly the same outcome on a C++11-compliant compiler:auto returnValue = futureWatcher.future().result();
QVector<QStringList> returnValue = futureWatcher.future().result();
As @jsulm mentioned,
auto
has been part of the C++ standard for 10 years (but it was widely available on common compilers years before that).If your compiler is moderately old, you can enable C++11 by adding
CONFIG += c++11
to your .pro file and re-running qmake. Nonetheless, we highly recommend that you use a recent version of your compiler + IDE, and that you take advantage of C++11 features in your code (which includesauto
and powerful template features). -
@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:
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
? -
-
@AnneRanch said in Need more help with C++ code syntax - QTConncurent and template:
Thanks for the history lesson, however "auto" was introduced to C much . much earlier...
The
auto
keyword in C means a totally different thing from theauto
we are talking about here in C++, introduced at C++11. It may be confusing that they chose to use the same keyword for a different purpose, but there you are.The
auto
you are referring to in C is a storage/scope specifier. Theauto
we are talking about here in C++ is for type inference. Quite different. -
@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. -
-
@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? -
@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)
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.
-
@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();
-
@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
-
@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