PDA

View Full Version : Is this the correct way of using QConcurrent::run() >



Hossein
12th October 2015, 08:14
Hello everyone,
I am trying to make some parts of my app run in a different thread than th UI thread, meanwhile I am trying to use a timer to show the elapsed time on the form.
For this I used the QConcurrent::run method like this :


void frmCustomNetwork::on_btnTrain_clicked()
{
try
{
if( P.size() == 0 || T.size() == 0)
{
QMessageBox::warning(this,"No Sample for training is set","You need to specify some samples with their respective desired outputs first");
return;
}


elapsedSeconds=0;
timer->start();
connect(&watcher,SIGNAL(finished()),this,SLOT(on_TimerTick( )));
future = QtConcurrent::run(this,&frmCustomNetwork::Rec,ui->chkPlot->isChecked());
watcher.setFuture(future);

}
catch(std::exception ex)
{
QMessageBox::critical(this,"Exception occured in on_btnTrain_clicked()",ex.what());
}
catch(...)
{
QMessageBox::critical(this,"Exception occured on_btnTrain_clicked()","Uknown Exception occured");
}
}



and this is the timerTick slot:


void frmCustomNetwork::on_TimerTick()
{
elapsedSeconds++;
if(watcher.isFinished())
{
timer->stop();
elapsedSeconds = 0;
return;
}

day = elapsedSeconds / (24*3600);
hour = (elapsedSeconds % (24*3600)) / 3600 ;
min = ((elapsedSeconds % (24*3600)) % 3600) / 60;
second = ((elapsedSeconds % (24*3600)) % 3600) % 60;

ui->lblElapsedTime->setText(QString::number(day)+" : "+QString::number(hour)+" : "+QString::number(min)+" : "+QString::number(second));
}


the problem that I am facing now is :
1.Is it the correct way of using QConcurent in first place?
2.How can I destroy the running thread ( the one spawned by QConcurrect::run()) when the window closes ( that is when the Rec() is not finished yet and is being executed in a separate thread, I suddently decide to close the app)

at the moment I am facing random crashes which I guess pretty much is because of the way I am creating and dealing with the new thread + timer.
I would be grateful If anyone could give me a hand in this
Thanks in advance

anda_skoa
12th October 2015, 10:27
One option you have is to wait on the future or future watchers when exiting.
Basically close the window and call watcher.waitForFinished() before exiting.

Cheers,
_

Hossein
12th October 2015, 11:52
One option you have is to wait on the future or future watchers when exiting.
Basically close the window and call watcher.waitForFinished() before exiting.

Cheers,
_
Thank you verymuch sir
But this would continue to execute the method till it ends, right? and this is not a wanted outcome.
suppose the user closes the app, thinking all is freed (resources I mean) and then tries to run or do whatever he was doing (possibly re executing the lengthy method )
How can I get rid of that spawned thread immediately? Is there anyway for that?

Lesiok
12th October 2015, 12:41
From QTimer doc : Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. I suggest using the class QElapsedTimer.

anda_skoa
12th October 2015, 13:26
How can I get rid of that spawned thread immediately? Is there anyway for that?

QtConcurrent uses the global instance of QThreadPool, you don't have any control over which thread is being used.

Stopping a thread requires that the code run by the thread regularily checks for a stop condition and a way for the main thread to make that stop condition to become true.

In the very special case of exiting the application, it might be OK to call terminate(), but I recommend to avoid that until it is the last resort.

Cheers,
_

Hossein
12th October 2015, 15:08
From QTimer doc : Timers will never time out earlier than the specified timeout value and they are not guaranteed to time out at the exact value specified. I suggest using the class QElapsedTimer.
thanks, but I cant use that, I need to update the time ( I need to show it to the user as well, and when I checked the documents, I couldn't find any events for QElapsedTimer that I can use instead of timers.


QtConcurrent uses the global instance of QThreadPool, you don't have any control over which thread is being used.

Stopping a thread requires that the code run by the thread regularily checks for a stop condition and a way for the main thread to make that stop condition to become true.

In the very special case of exiting the application, it might be OK to call terminate(), but I recommend to avoid that until it is the last resort.

Cheers,
_
That method is atomic, I mean I cant put anything into that, Its a member function of of a class which I have no control over it.

Lesiok
12th October 2015, 15:16
thanks, but I cant use that, I need to update the time ( I need to show it to the user as well, and when I checked the documents, I couldn't find any events for QElapsedTimer that I can use instead of timers.Of course You can. elapsedSeconds should be QElapsedTimer not int. Use QTimer only to update view not to count seconds.