QFutureWatcher - timing issue
-
I am using QFutureWatcher to account for a "delay of function" with over 10 seconds processing time.
The progress of QFutureWatcher is displayed in by QProgressDialog - using "progress bar" and showing percentage of delay completion.
Essentially I have an array 1 second delays and the size of the array gives me a way to select the desired full delay.
I am having an issue achieving full completion , full processing , of all QFutureWatcher iterations.
The discrepancy demonstrate itself by not displaying the percentage of completion on the progress bar.
If I set # of iterations to 5 I should see progress bar and it percentage to be 20 40 60 80 100. I do not.
It goes from 0% to 50% and terminates.If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
I did set the QProgressDialog to display immediately - it defaults to 4 seconds delay and I am receiving futureWatcher.waitForFinished(); BEFORE all iterations are done.
I do not expect precision, just general "what isi going on " is fine.
Not finishing the iterations is puzzling .
Any reasonable suggestion to the subject will be appreciated.
( Comments from "Peanut gallery" , such as "I do not use QProgressDialog " are unnecessary ).
Cheers and best in 2021
-
I am using QFutureWatcher to account for a "delay of function" with over 10 seconds processing time.
The progress of QFutureWatcher is displayed in by QProgressDialog - using "progress bar" and showing percentage of delay completion.
Essentially I have an array 1 second delays and the size of the array gives me a way to select the desired full delay.
I am having an issue achieving full completion , full processing , of all QFutureWatcher iterations.
The discrepancy demonstrate itself by not displaying the percentage of completion on the progress bar.
If I set # of iterations to 5 I should see progress bar and it percentage to be 20 40 60 80 100. I do not.
It goes from 0% to 50% and terminates.If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
I did set the QProgressDialog to display immediately - it defaults to 4 seconds delay and I am receiving futureWatcher.waitForFinished(); BEFORE all iterations are done.
I do not expect precision, just general "what isi going on " is fine.
Not finishing the iterations is puzzling .
Any reasonable suggestion to the subject will be appreciated.
( Comments from "Peanut gallery" , such as "I do not use QProgressDialog " are unnecessary ).
Cheers and best in 2021
@AnneRanch
You are still referring to / using this example, right? (https://www.bogotobogo.com/Qt/Qt5_QtConcurrent_QFutureWatcher_QProgressDialog_map.php)
How is your "work" task configured? How do you stop your task (when do you call
waitForFinished
?)If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
This looks like a wrong configuration
If you are using the example code (at least parts of it), then this
connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
should take care of your process dialog and its correct setup (set a range matching your total work and a correct update interval).
-
@AnneRanch
You are still referring to / using this example, right? (https://www.bogotobogo.com/Qt/Qt5_QtConcurrent_QFutureWatcher_QProgressDialog_map.php)
How is your "work" task configured? How do you stop your task (when do you call
waitForFinished
?)If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
This looks like a wrong configuration
If you are using the example code (at least parts of it), then this
connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
should take care of your process dialog and its correct setup (set a range matching your total work and a correct update interval).
@Pl45m4 said in QFutureWatcher - timing issue:
@AnneRanch
You are still referring to / using this example, right? (https://www.bogotobogo.com/Qt/Qt5_QtConcurrent_QFutureWatcher_QProgressDialog_map.php)
How is your "work" task configured? How do you stop your task (when do you call
waitForFinished
?)If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
This looks like a wrong configuration
If you are using the example code (at least parts of it), then this
connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
should take care of your process dialog and its correct setup (set a range matching your total work and a correct update interval).
Found the problem, but not the solution, not yet.
From get go I was not too happy with the tutorial which "comments " the C code in style:int a = 10 // set variable a to 10
The problem is in constructing the QProgressDialog using default constrictor. I am already setting some defaults to real values , but it is not enough.
I'll be replacing the tutorial default QProgressDialog with my own next. -
@Pl45m4 said in QFutureWatcher - timing issue:
@AnneRanch
You are still referring to / using this example, right? (https://www.bogotobogo.com/Qt/Qt5_QtConcurrent_QFutureWatcher_QProgressDialog_map.php)
How is your "work" task configured? How do you stop your task (when do you call
waitForFinished
?)If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
This looks like a wrong configuration
If you are using the example code (at least parts of it), then this
connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
should take care of your process dialog and its correct setup (set a range matching your total work and a correct update interval).
Found the problem, but not the solution, not yet.
From get go I was not too happy with the tutorial which "comments " the C code in style:int a = 10 // set variable a to 10
The problem is in constructing the QProgressDialog using default constrictor. I am already setting some defaults to real values , but it is not enough.
I'll be replacing the tutorial default QProgressDialog with my own next.@AnneRanch said in QFutureWatcher - timing issue:
I am already setting some defaults to real values
What defaults? The connection, I've shown above and which is used in your example, sets up the
QProgressDialog
according to yourQFutureWatchers
"watched" work.progressRangeChanged(int,int)
will set the range (0% - 100%) to (0, 10), where 10 = 100%. So eachiteration
(total of 10) equals 10%.
Every time oneiteration
is done (one iteration = count from 0 to 1000*1000*40),progressValueChanged(int)
is emitted and sets the corresponding percentage in yourQProgressDialog
.
Then, in the end,waitForFinished()
is called to "block" the main thread until all future work has been done (and to ensure that you have all results from all threads, when reaching this point in your code).Probably your
QElapsedTimer
causes the issue, because it traps your thread in yourdo - while
loop. -
@AnneRanch said in QFutureWatcher - timing issue:
I am already setting some defaults to real values
What defaults? The connection, I've shown above and which is used in your example, sets up the
QProgressDialog
according to yourQFutureWatchers
"watched" work.progressRangeChanged(int,int)
will set the range (0% - 100%) to (0, 10), where 10 = 100%. So eachiteration
(total of 10) equals 10%.
Every time oneiteration
is done (one iteration = count from 0 to 1000*1000*40),progressValueChanged(int)
is emitted and sets the corresponding percentage in yourQProgressDialog
.
Then, in the end,waitForFinished()
is called to "block" the main thread until all future work has been done (and to ensure that you have all results from all threads, when reaching this point in your code).Probably your
QElapsedTimer
causes the issue, because it traps your thread in yourdo - while
loop.OK, I admit I have a basic misunderstanding of the "connections" between parts of the code.
I need 10 second delay , I picked 10 iterations of 1 second time delay monitoring elapsed time instead of using magic numbers to eat CPU.
( if there is a better way to do that please make a suggestion how.)I have NOT changed any of the "connect" functions.
The progress of the delay is displayed in modal
QProgressDialog dialog ( "TEST window title ",
" BUTTON text", 0, iterations ,0 ,0);run as
dialog.exec();
The dialog shows progress of 10 % and then jumps to 50% and closes.
I monitor the entire time of the dialog.exec(); and it reads approximately 3 seconds.
Apparently I need to figure out HOW to actually read the futurewatcher SINGAL to find out WHY the values are not as expected AND where are they coming form.
I am not sure if I can read the values while running dialog.exec(); AKA how to access current values of interest.
I
-
@Pl45m4 said in QFutureWatcher - timing issue:
@AnneRanch
You are still referring to / using this example, right? (https://www.bogotobogo.com/Qt/Qt5_QtConcurrent_QFutureWatcher_QProgressDialog_map.php)
How is your "work" task configured? How do you stop your task (when do you call
waitForFinished
?)If I set # of iterations to 200 - is see percentage 1,2,3, etc up to 100 BUT it never runs thru ALL 200 iterations.
This looks like a wrong configuration
If you are using the example code (at least parts of it), then this
connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));
should take care of your process dialog and its correct setup (set a range matching your total work and a correct update interval).
Found the problem, but not the solution, not yet.
From get go I was not too happy with the tutorial which "comments " the C code in style:int a = 10 // set variable a to 10
The problem is in constructing the QProgressDialog using default constrictor. I am already setting some defaults to real values , but it is not enough.
I'll be replacing the tutorial default QProgressDialog with my own next.@AnneRanch said in QFutureWatcher - timing issue:
default constrictor
Are you coding in Python?
PS: sorry but I couldn't resist...
-
@AnneRanch said in QFutureWatcher - timing issue:
default constrictor
Are you coding in Python?
PS: sorry but I couldn't resist...
@Pablo-J-Rogina said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
default constrictor
Are you coding in Python?
PS: sorry but I couldn't resist...
I am about to start coding in machine language...
This Qt stuff with its defaults / inheritance etc. is driving me nuts.'BTW the "constrictor" I used does not do simple window title as advertised.
Wonder what other parameters passed to it do not work... -
Hi,
Please show the code you are currently using. That will help us better understand what happens to you.
-
Hi,
Please show the code you are currently using. That will help us better understand what happens to you.
@SGaist said in QFutureWatcher - timing issue:
Hi,
Please show the code you are currently using. That will help us better understand what happens to you.
Are you positive ?
My code is currently more debug lines than code and from past experience I am reluctant to post it . I do not need my coding style criticized by Peanut gallery .In the mean time
I think my issue is in interaction of QProgressDialog changing "the value" , and actually understanding` what is the value. I though it is the percentage of completion of the QProgressDialog "progress bar" related to # of iterations, but I may be wrong.QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); // Start the computation. qDebug()<<" Start the computation - "; qDebug()<< "apply delay function "spin" to each vector"; futureWatcher.setFuture(QtConcurrent::map(vector, spin)); // futureWatcher.setFuture(); // Display the dialog and start the event loop. qDebug()<<" RUN dialog.exec() Display the dialog and start the dialog event loop"; // dialog.setMaximum(50); // dialog.setRange(10, 50 ); qDebug()<<" START dialog.exec() " ; // ? << dialog.setRange(10,30); // progress dialog event loop //dialog.setAutoClose(false); // test do not close disklog when finished // show % of completion in progress bar // timing loop runs thru # of iterations // show / run modal dialog // NOTE perror is phoney // test real duration of dialog here QElapsedTimer timer_wait; timer_wait.start(); // futureWatcher.progressValue() qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue(); attempt to monitor the actual "value" dialog.exec(); // run modal dialog qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue();
My attempt to monitor the actual "value" , at least at start and the end of the
dialog.exec(); // run modal dialog
Not sure why
- the end is set at "10" - should be 100 , but how - default again ?
- is it even possible to monitor modal dialog for changes?
perhaps adding my own slots to connect to QProgressDialog ?
-
@AnneRanch said in QFutureWatcher - timing issue:
I do not need my coding style criticized by Peanut gallery .
I'd avoid getting rude.
@AnneRanch said in QFutureWatcher - timing issue:
the end is set at "10" - should be 100 , but how - default again ?
The dialog creation/initialisation is missing from your code snippet.
@AnneRanch said in QFutureWatcher - timing issue:
is it even possible to monitor modal dialog for changes?
perhaps adding my own slots to connect to QProgressDialog ?What monitoring do you have in mind ?
-
@AnneRanch said in QFutureWatcher - timing issue:
I do not need my coding style criticized by Peanut gallery .
I'd avoid getting rude.
@AnneRanch said in QFutureWatcher - timing issue:
the end is set at "10" - should be 100 , but how - default again ?
The dialog creation/initialisation is missing from your code snippet.
@AnneRanch said in QFutureWatcher - timing issue:
is it even possible to monitor modal dialog for changes?
perhaps adding my own slots to connect to QProgressDialog ?What monitoring do you have in mind ?
@SGaist said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
I do not need my coding style criticized by Peanut gallery .
I'd avoid getting rude.
@AnneRanch said in QFutureWatcher - timing issue:
the end is set at "10" - should be 100 , but how - default again ?
The dialog creation/initialisation is missing from your code snippet.
@AnneRanch said in QFutureWatcher - timing issue:
is it even possible to monitor modal dialog for changes?
perhaps adding my own slots to connect to QProgressDialog ?What monitoring do you have in mind ?
As fae as I can tell the QProgressDialog can only follow what QFutureWatcher SIGNALS value and range is being set.
Since I opeted to use QProgressDialog dialog,exec() I really have no tracking means to see these.
Of course I could replace the dialog,exec() with code from documents.OK, here is my current code - lock , stock and barrel...
#include "configuredialog.h" #include "ui_configuredialog.h" #include "project_commonheader.h" ConfigureDialog::ConfigureDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { ui->setupUi(this); } ConfigureDialog::~ConfigureDialog() { delete ui; } // #of iteration ?? netartion is actaully // % step // when in 20 it takes steps in 20 % of total // this emulates the time consuming function void spin(int& iteration) { #ifdef PROCESS #ifdef TRACE // qDebug() << "QDEBUG TRACE "; qDebug () << " delay spin pass #" << iteration ; qDebug() << "QDEBUG TRACE TASK \n\t\t emulate the time consuming function \n"; //qDebug() << "QDEBUG TRACE TASK \n\t\t find nearby BT devices \n"; #ifdef BYPASS qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; qDebug()<<"TEMPORARY EXIT "; //exit(99); #endif #endif #endif int static access; if(!access ) { #ifdef PROCESS qDebug() << "RUN START long process ...."; #endif access++; } #ifdef PROCESS qDebug() << "RUN CONTINUE long process ...."; // actuall steps MN // adding elapsed timer // int Time_Step = ui->spinBoxIterations_2->text().toInt(); #endif QElapsedTimer timer; timer.start(); //slowOperation(); // we want to measure the time of this slowOperation() // qDebug() << timer.elapsed(); //#ifdef BYPASS do { //qDebug() << " do / while timer.elapsed()"; ; }while(timer.elapsed() <= 1000); // MN 1 second Time_Step); //#endif #ifdef BYPASS const int work = 10000 * 1000 * 33; // increased by 1000 volatile int v = 0; // the time emulator for (int j = 0; j < work; ++j) ++v; // step delay loop MN #endif qDebug() << "Estimated single iteration delay elapsed time " << timer.elapsed()<< " mS"; #ifdef PROCESS qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId(); //slowOperation(); // we want to measure the time of this slowOperation() qDebug() << "Estimated single iteration delkay elapsed time " << timer.elapsed()<< " mS"; #endif qDebug() << "iteration # " << iteration << "in thread" << QThread::currentThreadId(); } #ifdef BYPASS What defaults? The connection, I've shown above and which is used in your example, sets up the QProgressDialog according to your QFutureWatchers "watched" work. progressRangeChanged(int,int) will set the range (0% - 100%) to (0, 10), where 10 = 100%. So each iteration (total of 10) equals 10%. Every time one iteration is done (one iteration = count from 0 to 1000*1000*40), progressValueChanged(int) is emitted and sets the corresponding percentage in your QProgressDialog. Then, in the end, waitForFinished() is called to "block" the main thread until all future work has been done (and to ensure that you have all results from all threads, when reaching this point in your code). Probably your QElapsedTimer causes the issue, because it traps your thread in your do - while loop. #endif // initialize time consuming task void ConfigureDialog::on_doTaskButton_clicked() { # ifdef TRACE qDebug() << "QDEBUG TRACE START void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; //qDebug()<<"TEMPORARY EXIT "; // return;#ifdef BYPASS #endif // start run overall timer QElapsedTimer timer; timer.start(); // Prepare the vector. // what does it really do ? int iterations = ui->spinBoxIterations->text().toInt(); // how may iotera5tions to display 100% competion ?? // temporary MN iterations = 10; qDebug() << " Setup # of iterations = toatal delay " << iterations << " seconds"; #ifdef PROCESS qDebug()<<" # of iterations ?? " << iterations ; // vector.append(i) LOOP "; // return; qDebug() << "Estimated elapsed time " << timer.elapsed()<< " mS"; // dynamic array # one for each iteration // how often to update progress dialog #endif qDebug() << " Setup # of iterations as vector array "; QVector<int> vector; for (int i = 0; i < iterations; ++i) { #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); } #ifdef BYPASS QLabel *label = new QLabel; QScrollBar *scrollBar = new QScrollBar; QObject::connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); #endif // return; // Create a progress dialog. implements iteration // shows progress ion % // BUG doe not finish 100% qDebug()<<" Setup Create a 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) QProgressDialog dialog ( "TEST window title ", " BUTTON text", 0, iterations ,0 ,0); //BUG did not set to TEST window title here // dialog.setWindowModality(Qt::WindowModal); // 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); // single shot label only //This is done querying the number of processor cores dialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed())); // Create a QFutureWatcher and connect signals and slots. qDebug()<<" Setup Create a QFutureWatcher"; QFutureWatcher<void> futureWatcher; qDebug()<<" setup futureWatcher and dialog connect SIGNAL SLOT "; // # of iterations ?? " << iterations ; // vector.append(i) LOOP "; qDebug()<<" 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 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))); // Start the computation. qDebug()<<" Start the computation - "; qDebug()<< "apply delay function spin to each vector"; futureWatcher.setFuture(QtConcurrent::map(vector, spin)); // futureWatcher.setFuture(); // Display the dialog and start the event loop. qDebug()<<" RUN dialog.exec() Display the dialog and start the dialog event loop"; // dialog.setMaximum(50); // dialog.setRange(10, 50 ); qDebug()<<" START dialog.exec() " ; // ? << dialog.setRange(10,30); // progress dialog event loop //dialog.setAutoClose(false); // test do not close disklog when finished // show % of completion in progress bar // timing loop runs thru # of iterations // show / run modal dialog // NOTE perror is phoney // test real duration of dialog here QElapsedTimer timer_wait; timer_wait.start(); // futureWatcher.progressValue() qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue(); dialog.exec(); // run modal dialog qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue(); //qDebug()<<" START Display current range " ; // ? << dialog.setRange(10,30); #ifdef BYPASS if( dialog.exec()) \ { perror("Accepted = 1 - sucess "); } else { perror("?? Accepted != 1 say what ?? "); } ; // timing loop runs thru # of iterations #endif qDebug()<<" END dialog.exec() "<< timer_wait.elapsed()<< " mS"; // qDebug() << "test real duration of dialog here " << timer_wait.elapsed()<< " mS"; return; qDebug() << "Completed END FULL Estimated elapsed time " << timer.elapsed()<< " mS"; // show last iteration result % qDebug()<<"last iteration resul t % "<< iterations; qDebug()<<" END Display current range ?? " ; // ? << dialog.setRange(10,30); // qDebug()<<" futureWatcher.waitForFinished()"; // when setAUtoCLose is true defualkt no need to wait for finshed ?? // test wait time if any // this makes no snese since connect(&futureWatcher, SIGNAL(finished()) // runs &dialog, SLOT(reset()) #ifdef PROCESS QElapsedTimer timer_wait; timer_wait.start(); futureWatcher.waitForFinished(); qDebug() << "test wait futureWatcher.waitForFinished() time if any " << timer_wait.elapsed()<< " mS"; // Query the future to check if was canceled. qDebug() << "DONE (was) Canceled?" << futureWatcher.future().isCanceled(); #endif # ifdef TRACE qDebug() << "QDEBUG TRACE END void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; //qDebug()<<"TEMPORARY EXIT "; // return;#ifdef BYPASS #endif } #ifdef BYPASS QFutureWatcher #ifdef BYPASS \temoprary bypaSS POROIGNAL #include "taskdialog.h" #include "ui_taskdialog.h" #include <QtConcurrent> #include <QProgressDialog> #include <qtconcurrentmap.h> TaskDialog::TaskDialog(QWidget *parent) : QDialog(parent), ui(new Ui::TaskDialog) { ui->setupUi(this); } TaskDialog::~TaskDialog() { delete ui; } void spin(int& iteration) { const int work = 1000 * 1000 * 40; volatile int v = 0; for (int j = 0; j < work; ++j) ++v; qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId(); } void TaskDialog::on_doTaskButton_clicked() { # ifdef TRACE qDebug() << "QDEBUG TRACE void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; qDebug()<<"TEMPORARY EXIT "; return;#ifdef BYPASS #endif // Prepare the vector. int iterations = ui->spinBoxIterations->text().toInt(); QVector<int> vector; for (int i = 0; i < iterations; ++i) vector.append(i); // Create a progress dialog. // all defualts ?? no form ?? QProgressDialog dialog; dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount())); dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount())); // Create a QFutureWatcher and connect signals and slots. QFutureWatcher<void> futureWatcher; QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); // Start the computation. // futureWatcher.setFuture(QtConcurrent::map(vector, spin)); futureWatcher.setFuture(QtConcurrent::map(vector, spin)); // Display the dialog and start the event loop. // this may be wrong dialog.exec(); // this may be wrong futureWatcher.waitForFinished(); // Query the future to check if was canceled. qDebug() << "Canceled?" << futureWatcher.future().isCanceled(); } #endif #endif #ifdef BYPASS // Operation constructor Operation::Operation(QObject *parent) : QObject(parent), steps(0) { pd = new QProgressDialog("Operation in progress.", "Cancel", 0, 100); connect(pd, SIGNAL(canceled()), this, SLOT(cancel())); t = new QTimer(this); connect(t, SIGNAL(timeout()), this, SLOT(perform())); t->start(0); } void Operation::perform() { pd->setValue(steps); //... perform one percent of the operation steps++; if (steps > pd->maximum()) t->stop(); } void Operation::cancel() { t->stop(); //... cleanup } #endif
And here is my current output
QDEBUG TRACE START void TaskDialog::on_doTaskButton_clicked() file ../CAT_V1/configuredialog.cpp function on_doTaskButton_clicked @line 111 Setup # of iterations = toatal delay 10 seconds Setup # of iterations as vector array Setup Create a QProgressDialog dialog - set paramaters Setup Create a QFutureWatcher setup futureWatcher and dialog connect SIGNAL SLOT setup future WatcherSIGNAL(finished() setup dialog, SIGNAL(canceled() Start the computation - apply delay function spin to each vector RUN dialog.exec() Display the dialog and start the dialog event loop START dialog.exec() futureWatcher.progressValue() 0 Estimated single iteration delay elapsed time 1001 mS iteration # 0 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 2 in thread 0x7f6d9e581700 Estimated single iteration delay elapsed time 1004 mS iteration # 1 in thread 0x7f6d9d57f700 Estimated single iteration delay elapsed time 1001 mS iteration # 3 in thread 0x7f6d9dd80700 Estimated single iteration delay elapsed time 1001 mS iteration # 4 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 6 in thread 0x7f6d9d57f700 Estimated single iteration delay elapsed time 1004 mS iteration # 5 in thread 0x7f6d9e581700 Estimated single iteration delay elapsed time 1001 mS iteration # 7 in thread 0x7f6d9dd80700 Estimated single iteration delay elapsed time 1001 mS iteration # 8 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 9 in thread 0x7f6d9d57f700 futureWatcher.progressValue() 10 END dialog.exec() 3034 mS
Note the last line - it should be approximately 10 seconds.
-
@SGaist said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
I do not need my coding style criticized by Peanut gallery .
I'd avoid getting rude.
@AnneRanch said in QFutureWatcher - timing issue:
the end is set at "10" - should be 100 , but how - default again ?
The dialog creation/initialisation is missing from your code snippet.
@AnneRanch said in QFutureWatcher - timing issue:
is it even possible to monitor modal dialog for changes?
perhaps adding my own slots to connect to QProgressDialog ?What monitoring do you have in mind ?
As fae as I can tell the QProgressDialog can only follow what QFutureWatcher SIGNALS value and range is being set.
Since I opeted to use QProgressDialog dialog,exec() I really have no tracking means to see these.
Of course I could replace the dialog,exec() with code from documents.OK, here is my current code - lock , stock and barrel...
#include "configuredialog.h" #include "ui_configuredialog.h" #include "project_commonheader.h" ConfigureDialog::ConfigureDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ConfigureDialog) { ui->setupUi(this); } ConfigureDialog::~ConfigureDialog() { delete ui; } // #of iteration ?? netartion is actaully // % step // when in 20 it takes steps in 20 % of total // this emulates the time consuming function void spin(int& iteration) { #ifdef PROCESS #ifdef TRACE // qDebug() << "QDEBUG TRACE "; qDebug () << " delay spin pass #" << iteration ; qDebug() << "QDEBUG TRACE TASK \n\t\t emulate the time consuming function \n"; //qDebug() << "QDEBUG TRACE TASK \n\t\t find nearby BT devices \n"; #ifdef BYPASS qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; qDebug()<<"TEMPORARY EXIT "; //exit(99); #endif #endif #endif int static access; if(!access ) { #ifdef PROCESS qDebug() << "RUN START long process ...."; #endif access++; } #ifdef PROCESS qDebug() << "RUN CONTINUE long process ...."; // actuall steps MN // adding elapsed timer // int Time_Step = ui->spinBoxIterations_2->text().toInt(); #endif QElapsedTimer timer; timer.start(); //slowOperation(); // we want to measure the time of this slowOperation() // qDebug() << timer.elapsed(); //#ifdef BYPASS do { //qDebug() << " do / while timer.elapsed()"; ; }while(timer.elapsed() <= 1000); // MN 1 second Time_Step); //#endif #ifdef BYPASS const int work = 10000 * 1000 * 33; // increased by 1000 volatile int v = 0; // the time emulator for (int j = 0; j < work; ++j) ++v; // step delay loop MN #endif qDebug() << "Estimated single iteration delay elapsed time " << timer.elapsed()<< " mS"; #ifdef PROCESS qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId(); //slowOperation(); // we want to measure the time of this slowOperation() qDebug() << "Estimated single iteration delkay elapsed time " << timer.elapsed()<< " mS"; #endif qDebug() << "iteration # " << iteration << "in thread" << QThread::currentThreadId(); } #ifdef BYPASS What defaults? The connection, I've shown above and which is used in your example, sets up the QProgressDialog according to your QFutureWatchers "watched" work. progressRangeChanged(int,int) will set the range (0% - 100%) to (0, 10), where 10 = 100%. So each iteration (total of 10) equals 10%. Every time one iteration is done (one iteration = count from 0 to 1000*1000*40), progressValueChanged(int) is emitted and sets the corresponding percentage in your QProgressDialog. Then, in the end, waitForFinished() is called to "block" the main thread until all future work has been done (and to ensure that you have all results from all threads, when reaching this point in your code). Probably your QElapsedTimer causes the issue, because it traps your thread in your do - while loop. #endif // initialize time consuming task void ConfigureDialog::on_doTaskButton_clicked() { # ifdef TRACE qDebug() << "QDEBUG TRACE START void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; //qDebug()<<"TEMPORARY EXIT "; // return;#ifdef BYPASS #endif // start run overall timer QElapsedTimer timer; timer.start(); // Prepare the vector. // what does it really do ? int iterations = ui->spinBoxIterations->text().toInt(); // how may iotera5tions to display 100% competion ?? // temporary MN iterations = 10; qDebug() << " Setup # of iterations = toatal delay " << iterations << " seconds"; #ifdef PROCESS qDebug()<<" # of iterations ?? " << iterations ; // vector.append(i) LOOP "; // return; qDebug() << "Estimated elapsed time " << timer.elapsed()<< " mS"; // dynamic array # one for each iteration // how often to update progress dialog #endif qDebug() << " Setup # of iterations as vector array "; QVector<int> vector; for (int i = 0; i < iterations; ++i) { #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); } #ifdef BYPASS QLabel *label = new QLabel; QScrollBar *scrollBar = new QScrollBar; QObject::connect(scrollBar, SIGNAL(valueChanged(int)), label, SLOT(setNum(int))); #endif // return; // Create a progress dialog. implements iteration // shows progress ion % // BUG doe not finish 100% qDebug()<<" Setup Create a 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) QProgressDialog dialog ( "TEST window title ", " BUTTON text", 0, iterations ,0 ,0); //BUG did not set to TEST window title here // dialog.setWindowModality(Qt::WindowModal); // 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); // single shot label only //This is done querying the number of processor cores dialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed())); // Create a QFutureWatcher and connect signals and slots. qDebug()<<" Setup Create a QFutureWatcher"; QFutureWatcher<void> futureWatcher; qDebug()<<" setup futureWatcher and dialog connect SIGNAL SLOT "; // # of iterations ?? " << iterations ; // vector.append(i) LOOP "; qDebug()<<" 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 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))); // Start the computation. qDebug()<<" Start the computation - "; qDebug()<< "apply delay function spin to each vector"; futureWatcher.setFuture(QtConcurrent::map(vector, spin)); // futureWatcher.setFuture(); // Display the dialog and start the event loop. qDebug()<<" RUN dialog.exec() Display the dialog and start the dialog event loop"; // dialog.setMaximum(50); // dialog.setRange(10, 50 ); qDebug()<<" START dialog.exec() " ; // ? << dialog.setRange(10,30); // progress dialog event loop //dialog.setAutoClose(false); // test do not close disklog when finished // show % of completion in progress bar // timing loop runs thru # of iterations // show / run modal dialog // NOTE perror is phoney // test real duration of dialog here QElapsedTimer timer_wait; timer_wait.start(); // futureWatcher.progressValue() qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue(); dialog.exec(); // run modal dialog qDebug()<<"futureWatcher.progressValue() " << futureWatcher.progressValue(); //qDebug()<<" START Display current range " ; // ? << dialog.setRange(10,30); #ifdef BYPASS if( dialog.exec()) \ { perror("Accepted = 1 - sucess "); } else { perror("?? Accepted != 1 say what ?? "); } ; // timing loop runs thru # of iterations #endif qDebug()<<" END dialog.exec() "<< timer_wait.elapsed()<< " mS"; // qDebug() << "test real duration of dialog here " << timer_wait.elapsed()<< " mS"; return; qDebug() << "Completed END FULL Estimated elapsed time " << timer.elapsed()<< " mS"; // show last iteration result % qDebug()<<"last iteration resul t % "<< iterations; qDebug()<<" END Display current range ?? " ; // ? << dialog.setRange(10,30); // qDebug()<<" futureWatcher.waitForFinished()"; // when setAUtoCLose is true defualkt no need to wait for finshed ?? // test wait time if any // this makes no snese since connect(&futureWatcher, SIGNAL(finished()) // runs &dialog, SLOT(reset()) #ifdef PROCESS QElapsedTimer timer_wait; timer_wait.start(); futureWatcher.waitForFinished(); qDebug() << "test wait futureWatcher.waitForFinished() time if any " << timer_wait.elapsed()<< " mS"; // Query the future to check if was canceled. qDebug() << "DONE (was) Canceled?" << futureWatcher.future().isCanceled(); #endif # ifdef TRACE qDebug() << "QDEBUG TRACE END void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; //qDebug()<<"TEMPORARY EXIT "; // return;#ifdef BYPASS #endif } #ifdef BYPASS QFutureWatcher #ifdef BYPASS \temoprary bypaSS POROIGNAL #include "taskdialog.h" #include "ui_taskdialog.h" #include <QtConcurrent> #include <QProgressDialog> #include <qtconcurrentmap.h> TaskDialog::TaskDialog(QWidget *parent) : QDialog(parent), ui(new Ui::TaskDialog) { ui->setupUi(this); } TaskDialog::~TaskDialog() { delete ui; } void spin(int& iteration) { const int work = 1000 * 1000 * 40; volatile int v = 0; for (int j = 0; j < work; ++j) ++v; qDebug() << "iteration" << iteration << "in thread" << QThread::currentThreadId(); } void TaskDialog::on_doTaskButton_clicked() { # ifdef TRACE qDebug() << "QDEBUG TRACE void TaskDialog::on_doTaskButton_clicked()"; qDebug() << "file " << __FILE__; qDebug() << "function "<<__FUNCTION__; qDebug() << "@line " << __LINE__; qDebug()<<"TEMPORARY EXIT "; return;#ifdef BYPASS #endif // Prepare the vector. int iterations = ui->spinBoxIterations->text().toInt(); QVector<int> vector; for (int i = 0; i < iterations; ++i) vector.append(i); // Create a progress dialog. // all defualts ?? no form ?? QProgressDialog dialog; dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount())); dialog.setLabelText(QString("Progressing using %1 thread(s)...").arg(QThread::idealThreadCount())); // Create a QFutureWatcher and connect signals and slots. QFutureWatcher<void> futureWatcher; QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); // Start the computation. // futureWatcher.setFuture(QtConcurrent::map(vector, spin)); futureWatcher.setFuture(QtConcurrent::map(vector, spin)); // Display the dialog and start the event loop. // this may be wrong dialog.exec(); // this may be wrong futureWatcher.waitForFinished(); // Query the future to check if was canceled. qDebug() << "Canceled?" << futureWatcher.future().isCanceled(); } #endif #endif #ifdef BYPASS // Operation constructor Operation::Operation(QObject *parent) : QObject(parent), steps(0) { pd = new QProgressDialog("Operation in progress.", "Cancel", 0, 100); connect(pd, SIGNAL(canceled()), this, SLOT(cancel())); t = new QTimer(this); connect(t, SIGNAL(timeout()), this, SLOT(perform())); t->start(0); } void Operation::perform() { pd->setValue(steps); //... perform one percent of the operation steps++; if (steps > pd->maximum()) t->stop(); } void Operation::cancel() { t->stop(); //... cleanup } #endif
And here is my current output
QDEBUG TRACE START void TaskDialog::on_doTaskButton_clicked() file ../CAT_V1/configuredialog.cpp function on_doTaskButton_clicked @line 111 Setup # of iterations = toatal delay 10 seconds Setup # of iterations as vector array Setup Create a QProgressDialog dialog - set paramaters Setup Create a QFutureWatcher setup futureWatcher and dialog connect SIGNAL SLOT setup future WatcherSIGNAL(finished() setup dialog, SIGNAL(canceled() Start the computation - apply delay function spin to each vector RUN dialog.exec() Display the dialog and start the dialog event loop START dialog.exec() futureWatcher.progressValue() 0 Estimated single iteration delay elapsed time 1001 mS iteration # 0 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 2 in thread 0x7f6d9e581700 Estimated single iteration delay elapsed time 1004 mS iteration # 1 in thread 0x7f6d9d57f700 Estimated single iteration delay elapsed time 1001 mS iteration # 3 in thread 0x7f6d9dd80700 Estimated single iteration delay elapsed time 1001 mS iteration # 4 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 6 in thread 0x7f6d9d57f700 Estimated single iteration delay elapsed time 1004 mS iteration # 5 in thread 0x7f6d9e581700 Estimated single iteration delay elapsed time 1001 mS iteration # 7 in thread 0x7f6d9dd80700 Estimated single iteration delay elapsed time 1001 mS iteration # 8 in thread 0x7f6db5c91700 Estimated single iteration delay elapsed time 1001 mS iteration # 9 in thread 0x7f6d9d57f700 futureWatcher.progressValue() 10 END dialog.exec() 3034 mS
Note the last line - it should be approximately 10 seconds.
@AnneRanch said in QFutureWatcher - timing issue:
Note the last line - it should be approximately 10 seconds.
Is this your only issue?! Are you aware that
QElapsedTimer
only counts the seconds from last (re-)start?!
So if you restart the same timer multiple times, it measures the time from last start to end only.Can you confirm that every single task needs about one 1 second?! Or is this output wrong and it only takes 3 secs for all 10 tasks, which should take 10?
-
@AnneRanch said in QFutureWatcher - timing issue:
Note the last line - it should be approximately 10 seconds.
Is this your only issue?! Are you aware that
QElapsedTimer
only counts the seconds from last (re-)start?!
So if you restart the same timer multiple times, it measures the time from last start to end only.Can you confirm that every single task needs about one 1 second?! Or is this output wrong and it only takes 3 secs for all 10 tasks, which should take 10?
@Pl45m4 said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
Note the last line - it should be approximately 10 seconds.
Is this your only issue?! ''
YESAre you aware that
QElapsedTimer
only counts the seconds from last (re-)start?!YES
So if you restart the same timer multiple times, it measures the time from last start to end only.
Name specific time that is incorrectly restarted that way .
Can you confirm that every single task needs about one 1 second?!
YES
I am after 10 seconds delay, using 10 iterations that = approximately 10 * 1 seconds. The time precision is irrelevant.Or is this output wrong and it only takes 3 secs for all 10 tasks, which should take 10?
YES
The desired execution of dialog.exec() is 10 seconds - the current execution takes approximately 3 seconds.
Here is a crazy idea
If I set the iteration to 50 - the total delay time is approximately 13
seconds.If I set the iteration to 100 - the total delay time is approximately 25 seconds.
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative - no need for parallel processing.
BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
Thinking up-loud - since each iteration runs in four threads - is the delay really 1 second? Sounds really crazy...
Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.
Could that be the issue?I should be able to track both SIGNALS - I 'll take a look how it can be done.
-
@Pl45m4 said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
Note the last line - it should be approximately 10 seconds.
Is this your only issue?! ''
YESAre you aware that
QElapsedTimer
only counts the seconds from last (re-)start?!YES
So if you restart the same timer multiple times, it measures the time from last start to end only.
Name specific time that is incorrectly restarted that way .
Can you confirm that every single task needs about one 1 second?!
YES
I am after 10 seconds delay, using 10 iterations that = approximately 10 * 1 seconds. The time precision is irrelevant.Or is this output wrong and it only takes 3 secs for all 10 tasks, which should take 10?
YES
The desired execution of dialog.exec() is 10 seconds - the current execution takes approximately 3 seconds.
Here is a crazy idea
If I set the iteration to 50 - the total delay time is approximately 13
seconds.If I set the iteration to 100 - the total delay time is approximately 25 seconds.
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative - no need for parallel processing.
BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
Thinking up-loud - since each iteration runs in four threads - is the delay really 1 second? Sounds really crazy...
Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.
Could that be the issue?I should be able to track both SIGNALS - I 'll take a look how it can be done.
@AnneRanch said in QFutureWatcher - timing issue:
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative
In its own threads.
- no need for parallel processing.
Then why do you explicitly use parallel processing? ... then wonder why the time is approximately scaled by the number of pooled threads ... this is all very confusing ...
BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
QDialog::exec
doesn't use any cores at all. YourQtConcurrent::map
does.Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.There are no iterations.
QDialog::exec
waits for an event to appear in the event queue, if there's none it just sleeps until one happens to appear (be it a GUI event or a signal/slot meta-call - a.k.a. queued connection call). -
@AnneRanch said in QFutureWatcher - timing issue:
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative
In its own threads.
- no need for parallel processing.
Then why do you explicitly use parallel processing? ... then wonder why the time is approximately scaled by the number of pooled threads ... this is all very confusing ...
BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
QDialog::exec
doesn't use any cores at all. YourQtConcurrent::map
does.Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.There are no iterations.
QDialog::exec
waits for an event to appear in the event queue, if there's none it just sleeps until one happens to appear (be it a GUI event or a signal/slot meta-call - a.k.a. queued connection call).@kshegunov said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative
In its own threads.
- no need for parallel processing.
Then why do you explicitly use parallel processing? ... then wonder why the time is approximately scaled by the number of pooled threads ... this is all very confusing ...
As pointed out many times - I am following a tutorial.
I have also said that most of the tutorial steps are not commented WHAT they do . Basically blindly following the tutorial - and the result is obvious.
Confusing to you , frustrating to me.BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
Which does not make sense.
QDialog::exec
doesn't use any cores at all. YourQtConcurrent::map
does.Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.I do not like to get sidteracked by niticking on sentic.
The QProgresDialog ( n tutorial ) outputsdialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed()));
So why should I question WHO is using the threads - dialog or QtConcurrent?
How does that leads to solution ?
I am not complaining about your comment, just trying to maintain some priorities in logic to find the problem.> There are no iterations.
QDialog::exec
waits for an event to appear in the event queue, if there's none it just sleeps until one happens to appear (be it a GUI event or a signal/slot meta-call - a.k.a. queued connection call).**OK THIS IS VERY GOOD POINT and IMPORTANT,
My test delay process is initialized by standard button push...
"" can somebody describe WHAT EVENT actually starts QProgressDialog::exec ?**I am under the impression that QProgressDialog constructor does that.
Am I wrong ?And HOW does the delay process continue from starting point ?
Secondly
so what are "iterations" for ?
They are passed to QProgressDialog constructor...Challenge to group
Would somebody some up with old fashioned flow chart to put the process
from "button pushed" to "delay completed " ?
My verbal output track sort of does it , but obviously needs better explanations what each step does.New crazy thought - the original tutorial code worked (!) but it used default
constructor - without any parameters passed to the class and without setting any parameters in code - just used all unpublished defaults.
With one of the defaults , forgot which one, the actual progress bar supposedly should show up AFTER 4 second delay .In current failure mode the progress bar shows 10% (immediately) then shows 50% ( after about 3 seconds) - the percentage is exactly "4 seconds " between the updates when iteration is set to 10 !
-
@kshegunov said in QFutureWatcher - timing issue:
@AnneRanch said in QFutureWatcher - timing issue:
The "spin" delay runs in its own thread - which is not necessary since the delay is cumulative
In its own threads.
- no need for parallel processing.
Then why do you explicitly use parallel processing? ... then wonder why the time is approximately scaled by the number of pooled threads ... this is all very confusing ...
As pointed out many times - I am following a tutorial.
I have also said that most of the tutorial steps are not commented WHAT they do . Basically blindly following the tutorial - and the result is obvious.
Confusing to you , frustrating to me.BUT the dialog.exec() "uses" all four CPU cores ( as noted in the progress dialog text ) - hence four threads .
Which does not make sense.
QDialog::exec
doesn't use any cores at all. YourQtConcurrent::map
does.Keeping in mind that I really do not have means monitoring the dialog.exec()
iterations.I do not like to get sidteracked by niticking on sentic.
The QProgresDialog ( n tutorial ) outputsdialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed()));
So why should I question WHO is using the threads - dialog or QtConcurrent?
How does that leads to solution ?
I am not complaining about your comment, just trying to maintain some priorities in logic to find the problem.> There are no iterations.
QDialog::exec
waits for an event to appear in the event queue, if there's none it just sleeps until one happens to appear (be it a GUI event or a signal/slot meta-call - a.k.a. queued connection call).**OK THIS IS VERY GOOD POINT and IMPORTANT,
My test delay process is initialized by standard button push...
"" can somebody describe WHAT EVENT actually starts QProgressDialog::exec ?**I am under the impression that QProgressDialog constructor does that.
Am I wrong ?And HOW does the delay process continue from starting point ?
Secondly
so what are "iterations" for ?
They are passed to QProgressDialog constructor...Challenge to group
Would somebody some up with old fashioned flow chart to put the process
from "button pushed" to "delay completed " ?
My verbal output track sort of does it , but obviously needs better explanations what each step does.New crazy thought - the original tutorial code worked (!) but it used default
constructor - without any parameters passed to the class and without setting any parameters in code - just used all unpublished defaults.
With one of the defaults , forgot which one, the actual progress bar supposedly should show up AFTER 4 second delay .In current failure mode the progress bar shows 10% (immediately) then shows 50% ( after about 3 seconds) - the percentage is exactly "4 seconds " between the updates when iteration is set to 10 !
@AnneRanch said in QFutureWatcher - timing issue:
As pointed out many times - I am following a tutorial.
I have also said that most of the tutorial steps are not commented WHAT they do . Basically blindly following the tutorial - and the result is obvious.Then read in docs what they do so you understand it, at least that's my advice.
QtConcurrent::map
isn't an alien we need a team of scientists to talk to, right? Just look it up, that's what I do when I follow tutorials.Confusing to you , frustrating to me.
Yes, yes, frustration leads to anger, anger leads to the dark side and all that. Less emotion, more practicality helps, I've found out.
I do not like to get sidteracked by niticking on sentic.
Actually you do, you just don't realize it. You have an unknown machine you're trying to figure out, but you claim you're not interested in how the cogs it's made of fit together. Should I mention such an approach is utterly futile?
The QProgresDialog ( n tutorial ) outputs
dialog.setLabelText(QString("Progressing using %1 thread(s)...\nTODO Elapsed time %2 [mS] ") .arg(QThread::idealThreadCount()).arg(timer.elapsed()));
So? This is evaluated before the dialog is even shown to the screen and has nothing to do with the dialog itself.
So why shoudI question WHO is using the threads - dialog or QtConcurren ?
It should, so you know where the problem lies. If you don't understand where the error is, then you're not going to be able to fix it, ever.
How does that leads to solution?
I don't know exactly what kind of solution you expect as I can't seem to fathom the problem. You split and process some vector in several threads, I get that. But I don't get what times and delays and elapsed timers have to do with it ...
For reference, what's the output of the following snippet:
QObject::connect(&futureWatcher, &decltype(futureWatcher)::progressRangeChanged, [] (int from, int to) -> void { qDebug() << "Map from " << from << " to " << to; }); QObject::connect(&futureWatcher, &decltype(futureWatcher)::progressValueChanged, [] (int value) -> void { qDebug() << "Map progress: " << value; });
-
Assuming the QprogressDialog is advanced / controlled by QFutureWacher SIGNALs of :"value" and "range"
I have added means of monitoring these signals
// create test SLOT to monitor progressValueChanged(int)
qDebug() << "create test SLOT to monitor progressValueChanged(int)";
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), this, SLOT(on_doTaskButton_2_clicked));
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)),this, SLOT(on_doTaskButton_3_clicked)));The result output is here
Start the computation - apply delay function spin to each vector RUN dialog.exec() Display the dialog and start the dialog event loop START dialog.exec() futureWatcher.progressValue() 0 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 0 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 1 Estimated single iteration delay elapsed time 1001 mS iteration # 0 in thread 0x7f380b7fe700 Estimated single iteration delay elapsed time 1001 mS iteration # 1 in thread 0x7f37fbfff700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 2 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 3 Estimated single iteration delay elapsed time 1001 mS iteration # 2 in thread 0x7f3808eea700 Estimated single iteration delay elapsed time 1008 mS iteration # 3 in thread 0x7f37fb7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 4 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 5 Estimated single iteration delay elapsed time 1001 mS iteration # 5 in thread 0x7f37fbfff700 Estimated single iteration delay elapsed time 1008 mS iteration # 4 in thread 0x7f380b7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 6 Estimated single iteration delay elapsed time 1001 mS iteration # 6 in thread 0x7f3808eea700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 7 Estimated single iteration delay elapsed time 1001 mS iteration # 7 in thread 0x7f37fb7fe700 Estimated single iteration delay elapsed time 1001 mS iteration # 8 in thread 0x7f37fbfff700 Estimated single iteration delay elapsed time 1001 mS iteration # 9 in thread 0x7f380b7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 8 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 9 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 10 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 11 futureWatcher.progressValue() 10 END dialog.exec() 3030 mS
Conclusion
the SIGNAL monitoring the value is changed 11 times - pretty much what is expected. I'll add showing the actual "value" at each time int changes - just to further verify it - it should be 10, 20, 30 etc.The range does not change and it should not - should remain 0 thru 100.
-
Assuming the QprogressDialog is advanced / controlled by QFutureWacher SIGNALs of :"value" and "range"
I have added means of monitoring these signals
// create test SLOT to monitor progressValueChanged(int)
qDebug() << "create test SLOT to monitor progressValueChanged(int)";
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), this, SLOT(on_doTaskButton_2_clicked));
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)),this, SLOT(on_doTaskButton_3_clicked)));The result output is here
Start the computation - apply delay function spin to each vector RUN dialog.exec() Display the dialog and start the dialog event loop START dialog.exec() futureWatcher.progressValue() 0 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 0 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 1 Estimated single iteration delay elapsed time 1001 mS iteration # 0 in thread 0x7f380b7fe700 Estimated single iteration delay elapsed time 1001 mS iteration # 1 in thread 0x7f37fbfff700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 2 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 3 Estimated single iteration delay elapsed time 1001 mS iteration # 2 in thread 0x7f3808eea700 Estimated single iteration delay elapsed time 1008 mS iteration # 3 in thread 0x7f37fb7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 4 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 5 Estimated single iteration delay elapsed time 1001 mS iteration # 5 in thread 0x7f37fbfff700 Estimated single iteration delay elapsed time 1008 mS iteration # 4 in thread 0x7f380b7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 6 Estimated single iteration delay elapsed time 1001 mS iteration # 6 in thread 0x7f3808eea700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 7 Estimated single iteration delay elapsed time 1001 mS iteration # 7 in thread 0x7f37fb7fe700 Estimated single iteration delay elapsed time 1001 mS iteration # 8 in thread 0x7f37fbfff700 Estimated single iteration delay elapsed time 1001 mS iteration # 9 in thread 0x7f380b7fe700 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 8 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 9 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 10 QDEBUG TRACE track SIGNAL SLOT file ../CAT_V1/configuredialog.cpp function on_doTaskButton_2_clicked @line 512 SLOT value access 11 futureWatcher.progressValue() 10 END dialog.exec() 3030 mS
Conclusion
the SIGNAL monitoring the value is changed 11 times - pretty much what is expected. I'll add showing the actual "value" at each time int changes - just to further verify it - it should be 10, 20, 30 etc.The range does not change and it should not - should remain 0 thru 100.
@AnneRanch said in QFutureWatcher - timing issue:
The range does not change and it should not - should remain 0 thru 100.
I somehow doubt that assertion, more specifically the numbers you cite, and the conclusions you draw from it. This is why I requested the output from the snippet in my previous post.
-
"Programs written with QtConcurrent automatically adjust the number of threads used according to the number of processor cores available. "
Hence there is no single usage of QFuture vectors - but FOUR of them are used running in four CPU cores at once.
Hence QProgressDialog "runs out" the correctly timed iterations FOUR times faster.
Thus the total desired time delay is incorrect. -
"Programs written with QtConcurrent automatically adjust the number of threads used according to the number of processor cores available. "
Hence there is no single usage of QFuture vectors - but FOUR of them are used running in four CPU cores at once.
Hence QProgressDialog "runs out" the correctly timed iterations FOUR times faster.
Thus the total desired time delay is incorrect.@AnneRanch said in QFutureWatcher - timing issue:
FOUR times faster.
Four threads won't increase the processing time of your whole task by a factor of four (if they share the same data)
Might be interesting:
(esp. the Concurrent part)