Run the code continuously until "Stop" is pressed - c++

I want to execute some code when I press a "Start" button and it have it continue running until I press "Stop".
However, with the following code once I press "Start", I can't press "Stop" anymore:
void MainWindow::on_pushButton_clicked()
{
if (ui->pushButton->text()=="Start") {
ui->pushButton->setText("Stop");
vec spectrum_sensed,Sn,sigma,alpha;
mat ydata;
condition=true;
while (condition) {
cvec uhd_samples = to_cvec(randn(Nsamples),randn(Nsamples));
ydata=spectrum->dft(uhd_samples,Ndft,Nband);
myplot->Plot_data(spectrum_sensed,Ndft);
}
}
else {
ui->pushButton->setText("Start");
condition=false;
myplot->clear_plot();
}
}

Qt's GUI runs in a single thread, and if your code blocks that thread, things like mouse clicks won't ever get handled (because the thread is busy doing nothing but calculating your data), and so your GUI freezes up.
As for how to change your program so that doesn't happen, you have a few options:
You could just throw a call to qApp->processEvents() into your calculation loop. That way Qt will get a chance to handle things like mouse clicks while you are calculating. That's the easiest way to go, but it can bite you if you're not careful -- for example if you've set up some other code so that a mouse click causes your MainWindow to be deleted, then you're likely to crash because after processEvents() returns it find itself executing in the on_pushButton_clicked() method of a now-deleted MainWindow object(!).
You could spawn a separate thread (using the QThread object) and run your calculation loop there. This is probably the most efficient approach, since on a multicore CPU it will let the GUI event loop run on one core while the calculations-loop simultaneously runs on another core, and so neither loop will slow the other one down. Note that this approach only works if your calculation loop doesn't touch any of the Qt GUI stuff -- Qt's GUI widgets are meant to be accessed only by the GUI thread, and if you try to examine them or modify them from a different thread, bad things will happen.
You could "unwrap" your loop so that it's no longer a synchronous loop but rather more like a state machine: That is, move the declarations of your calculation's state variables (spectrum_sensed, Sn, sigma, alpha, and ydata) out of the method, so that they are now member variables of the MainWindow class instead. Then write a Slot method that just does one iteration of your while loop (or maybe a small number of iterations, depending on how long each iteration takes), and then (within a few dozen milliseconds) calls QTimer::singleShot(0, this, SLOT(TheCalculationSlotMethodName()) and returns. That QTimer::singleShot() call will cause your calculation-slot-method to be called again on the next iteration of the Qt event loop, whereupon it can do a little bit more calculation. When the user clicks the "Stop" button, just have your on_stopButton_Pushed() slot set a boolean or something so that your calculation-method will know not to call QTimer::singleShot() anymore. I like this approach because there is little risk of race conditions or re-entrancy problems.

Related

How can I stop a long for loop when the widget (QDialog) running it is closed without multithreading?

I have a quite lengthy foreach loop in a QDialog. It basically looks like this:
foreach (xxx, xxx) {
... doSomeStuff ...
QApplication::processEvents();
if (m_cancelMapLoading) {
break;
}
}
m_cancelMapLoading is set to true by clicking a "Cancel" button. The QApplication::processEvents(); makes this possible.
This works quite fine, but if the dialog is closed as long as that foreach loop still runs, it continues running. I tried to set m_cancelMapLoading to true in each function closing the dialog, but this does not help.
I also tried to test not only for m_cancelMapLoading being true, but also for isVisible(). This actually stops the dialog, but it re-opens it at once without the GUI elements in it.
Unfortunately, QtConcurrent::run etc. can't be used for the function, because the data structures that are manipulated by the foreach loop are not thread safe.
Is there a convenient way to solve this?
You can use a QTimer and Qt's parent-child structure to your advantage here. QTimer with a timeout value of zero has a special meaning in Qt
As a special case, a QTimer with a timeout of 0 will time out as soon
as all the events in the window system's event queue have been
processed. This can be used to do heavy work while providing a snappy
user interface:
So you could do something like
void Dialog::beginDoingStuff()
{
m_timer = new QTimer(this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(processData());
m_timer->start(0);
}
void Dialog::processData()
{
// Perform one cycle of your process here
}
This will perform the processData() function in the same thread as the rest of the dialog, and when the dialog is destroyed by being closed, the timer will be deleted (because it's parent is the dialog), meaning the processing will stop.
A good and quite easy way to unload your GUI from heavy processing is assigning it to another thread or QtConcurrent.
You could then either poll a "should-I-terminate-yet?" variable or terminate the thread manually when it is no longer needed.
I highly recommend a parallel processing since offers better control rather than doing a "DoEvents"-like queue emptying.
We actually managed to solve the problem by connecting the dialog's finished signal to the click slot of the cancel button. This actually stops the loop in all circumstances.
We also introduced starting the function by a QTimer (for a nicer implementation not blocking the function where it's started), but this does not stop the loop (perhaps because we don't destroy the dialog when it's closed).
Thanks for all help :-)

How do I stop and start a loop in QT?

I've been trying to figure out how to make the program stop in a for-loop and wait for a button to be clicked and the for-loop continues.
Isn't there any easy way to stop the loop like QSystem.stop() and in the button clicked function QSystem.star() and the loop continues.
In C++ you could use system("pause") or the program stopped when you used a cin<<. But how do i do this in QT?
Since the userinterface needs its code to run, if you halt event loop (which also means that any function that gets called from within the event loop is blocking, waiting for some event), you also halt the user interface, which means clicks into the window won't be processed. That's why in event based programming, which is what all UI kits do, it is essential to return to the main event handler loop as quickly as possible.
What you can do is create a second thread and wait on a condition variable. The GUI thread can signal that condition variable in the button click event slot.
In C++ you could use system("pause") or the program stopped
Exactly: The program is stopped. Which means it won't fetch events from the operating system. However receiving data from stdin is not an event. It's blocking on streamed I/O. Graphical user interfaces are event based though.
Note that conceptually it's not really impossible to think of a user interface to provide streaming I/O channels. However that doesn't work in single threaded programs. You need parallel execution (coroutines, threads, or such) for a concept like this to work.
You don't need threads, nested event loop will do the job.
int waitUntilSignalIsEmitted(QObject *sender, const char *signal) {
QEventLoop loop;
connect(sender, signal,
&loop, SLOT(quit()));
return loop.exec();
}
// usage:
while(yourLoopCondition) {
// some stuff
...
// pause here
waitUntilSignalIsEmitted(yourContinuationButton, SIGNAL(clicked()));
// loop continuation
...
}

How to stop a function which is still computing with button stop?

I've an application visual c++ written using vs2010,
I have two buttons: "start" and "stop",the first one calls a function that takes a lot of time to process, so in a certain moment I'd like to stop the computation pressing stop button. But in my application the button start seems still clicked (I think it's waiting for the return of the function) and all the other buttons appear to be disabled. Even if I had a wonderful stop function, I could not active because I'm not able to click on button stop. Solutions,ideas,using threads,easy example? Thanks.
You need to run your calculations in another thread. Otherwise your gui freezes until your calculations are done (because only one thing can be done at the moment).
If you are using some modern compiler look at std::thread.
other solutions are boost threads or even microsoft threads.
If your computation is a loop, it may be quite easy to check at each iteration if your User wants to stop the computation.
In the computation thread:
while(compute){
// one loop of computation
}
While your GUI thread can set computationto false through your stop button.
I hope it helps
Note: In c++ as in java Swing etc.., the GUI has it's own thread (not really visible to the developer) and you should never do heavy tasks in it. For instance, every callbacks for buttons should be as small as possible to keep your GUI responsive. This thread's job is just to drive your application.
Button 1 -> onClick =
{
start thread -> { do stuff here }
}
BUtton 2 -> onClick =
{
close thread
}
Be careful when forcibly closing a thread because you can leak memory !
http://msdn.microsoft.com/it-it/library/system.componentmodel.backgroundworker%28v=vs.110%29.aspx
BackgroundWorker is perfect for this use!
First you need to imports the namespace
using System.Threading;
then use the following code :
Thread T=new Thread(Your Code Goes method name);
your method name()
{
// your code goes here
}
T.Start();
then
T.Abort();

How to show a QMessageBox completely before the next function call

I want to use a QMessageBox to announce a short waiting interval to the user.
QMessageBox* box(new QMessageBox(QMessageBox::Information,"Parser","Processing " + mFileName));
box->setStandardButtons(QMessageBox::NoButton);
box->setWindowModality(Qt::WindowModal);
box->show();
QApplication::processEvents();
parser.analyseFile(mFileName);
box->hide();
box->deleteLater();
QApplication::processEvents();
The function only takes few seconds.
The box gets displayed but neither the icon nor the text is shown in time before the function finishes. Why does QApplication::processEvents(); not prevent the program from continuation before the box is completely shown.
Is it possible to achieve the desired behaviour without resorting to threads.
Doing the processing in a separate thread would be preferable, since that would leave the GUI thread free to do things like handle mouse events, window resizes, etc, while the task is being completed; that way the GUI won't "freeze up" temporarily.
If you don't want to spawn a thread, however, you can call processEvents() periodically from within your analyseFile() function and that will give you roughly the same behavior. Try to call it at least every 50mS to avoid sluggish GUI response.
A second possibility might be to add a slot somewhere:
void MyClass :: ParseFile()
{
parser.analyseFile(mFileName);
box->hide();
box->deleteLater();
}
... and then invoke that asynchronously like this:
QTimer::singleShot(0, this, SLOT(ParseFile()));
... that might give the windowing system enough time to finish displaying the QMessageBox before ParseFile() executes, or it might not (in which case you could try to increase the delay argument from 0 to, say, 100 milliseconds instead). That's a little hacky, but it could work.

How to put wait condition in Signal-Slot?

I am doing one web related project. Recently I hit on this situation. This is just a stub
Class My_Class
{
public:
My_Class();
void start();
public slots():
void after_Load_Function();
}
My_Class::My_Class()
{
//Some initializations
connect(WebPage,SIGNAL(finished()),this,SLOTS(after_Load_Function()));
}
void My_Class::start()
{
WebPage->load();
}
void My_Class::after_Load_Function()
{
//Do something with the finished WebPage
}
int main(int argc,char * argv[])
{
//Some Qt things
My_Class a;
a.start();
}
"WebPage" emits the signal "finished" when it loaded fully.
Now the problem is before the "webPage" got loaded the "start" is returning. Thereby the control reaches the "main". So, now the control should return from "start" only after "after_Load_Function" finishes it's job. Thereby I want the below sequence,
main creates the My_Class object A.
main calls "start" from A.
start calls load from "WebPage" and it waits untill the "WebPage" emits "finished",
and that emit in turn calls the "after_Load_Function", and "after_Load_Function"
finishes it's job.
now, the "start" returns
main returns
But, I don't know how to make this kind of wait condition. How can I go about it?
You can do this by running a local event loop, letting the components process network income and load the page. When they emit the signal, you execute a slot on the event loop to quit it.
void My_Class::start()
{
QEventLoop qel;
QObject::connect(WebPage, SIGNAL(finished()), &qel, SLOT(quit()));
WebPage->load();
qel.exec();
}
I've been using this before and it works fine. I don't advice to use this too often though, because it will process events, including those that the caller of start might not be expecting to be processed during the call to start, so you need to document this to its callers. You can prevent the processing of some events by passing certain flags to QEventLoop::exec, like preventing to process user interface events.
You should never wait in UI code. You need to break your "main" function into pieces so the later part can be executed separately.
Use condition variables thats what they are used for. You can make threads wait on a condition variable and proceed when notified.
The WebPage->load() method is asynchronous, meaning that it runs immediately, not when the loading is complete. The operation runs in the background while you go to do other things.
This is considered a good thing, as it enables your app to be more responsive and get more done. For example, if your app has a GUI, you could update the GUI with some sort of animation that indicates that the web page is being retrieved.
If you prefer a model in which the application blocks until the page is fully loaded, then consider making this change:
void My_Class::start()
{
WebPage->load();
while (!WebPage->isLoaded())
Sleep(1);
after_Load_Function();
}
Notes:
the Sleep function will work on Windows. If you are on a Unix OS you can use usleep.
since this function will effectively block until the web page is loaded, there is no reason to use the signal from the web page object, you can just simply call your handler after the wait completes, as this will make your handler run in the same thread.
doing this is really bad practice. You may get away with it if your program is command line and has no GUI and/or event loop, but you should consider a better design for your app where the loading of web pages does not block the whole app.