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

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();

Related

ProcessMessages on OnShow Event c++ builder

I'm using c++ builder (bcb6) and on:
FormShow
event there is:
Application->ProcessMessages
I would like to know what exactly the responsibility of:
Application->ProcessMessages
What exactly it did? and when we shall use by that? when it can cause exp.?
Thanks!
The BDS 2006 IDE help states for Application->ProcessMessages this:
Interrupts the execution of an application so that it can process the message queue.
Call ProcessMessages to permit the application to process messages that are currently in the message queue. ProcessMessages cycles the Windows message loop until it is empty, and then returns control to the application.
Neglecting message processing affects only the application calling ProcessMessages, not other applications. In lengthy operations, calling ProcessMessages periodically allows the application to respond to paint and other messages.
ProcessMessages does not allow the application to go idle, whereas HandleMessage does.
so what for it is?
It allows to respond to Windows messages in case your app is blocking normal WindProc operation (inside VCL). For example if you got some lengthy computation on some event that takes minutes the application would freeze (can not click,move,resize,redraw,... until operation is done). If you once in a time call ProcessMessages from that long loop (timers would also not work during that time) that will allow to make your app responsive during this time... so it will not freeze.
I usually use threads or OnIdle event instead for such computations so the main App is not blocked at all.
I am reluctant to believe that OnShow is called during such blocking. I would place the ProcessMessages inside the computation that blocks the App (if the computations is inside the OnShow then it is OK otherwise it would be useless. Anyway OnShow is called only if your Form is turning to Visible do not mistake it for OnActivate or OnPaint.
small example
Create empty form app and place 2 buttons in it (btStart,btStop) then create on click event for them as following:
//---------------------------------------------------------------------------
bool go=false;
//---------------------------------------------------------------------------
void __fastcall TForm1::btStartClick(TObject *Sender)
{
int i=0;
for (go=true;go;)
{
Caption=i; i++;
Application->ProcessMessages();
Sleep(100);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btStopClick(TObject *Sender)
{
go=false;
}
//---------------------------------------------------------------------------
When you start app and click btStart it will start incrementing integer in Caption field of the Form1 and stop when you click btStop. during counting the App is still responsive (can click,move,resize,...). You need to stop before closing App is possible (destructors wait for returning from all events). if you rem out the Application->ProcessMessages(); then the App will count but will never stop because you can not click on btStop due to the freeze. To close click on the IDE and press CTRL+F2.
Hope it clears things a bit.

Run the code continuously until "Stop" is pressed

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.

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 :-)

MS Visual C++ Starting a function by clicking a button without blocking a dialog

I've created a dialog based MFC application on MS Visual Studio 2013. To the dialog, I've added ActiveX elements and some other list elements to show text output. One of the buttons with the ID IDC_BUTTONLAUNCH calls a function like
void CpiezcamDlg::OnBnClickedButtonlaunch()
{
SweepAndImage();
}
The function SweepAndImage(), which is a member of the class CpiezcamDlg and a bit more expensive (it takes about 10 sec). The function also calls updates to the list elements. There is also a Sleep function inside of SweepAndImage(). The result is that during the call of this function, the complete dialog is "blocked" and doesn't react (which makes sense). I've just started with MFC this week so my knowledge is rather limited. I tried to do
void CpiezcamDlg::OnBnClickedButtonlaunch()
{
#pragma omp parallel
{
#pragma omp single nowait
SweepAndImage();
}
}
to sort of "fork" the function into another thread. Since there's an implicit barrier at the end of the omp pragma, this doesn't work. I guess I need some sort event handler that is running in the background of my application and see if that button was clicked. Any kind of help or link is appreciated. If more information is needed, I'll add it.
OpenMP uses fork and thread to do work. It will not really do what you wish here.
MFC's GUI is running on the main thread. SweepAndImage will be run in a separate thread however OnBnClickedButtonlaunch will block waiting for SweepAndImage to return from doing work and then it will continue on. Because the main thread has been blocked updates to the GUI will also halt. Windows/MFC has a hidden window message pump that is abstracted away. That pump relies on event handlers (ie. your button press method) not blocking for too long so that the pump can continue on with the next event in the queue.
Since you are using MFC, MFC does have support for multithreading. I would recommend starting with this MSDN article
What you can do is create a new thread (see the article above) in your button handler that spawns off some work. That will allow the main thread to continue immediately and continue processing windows events in its pump.
To be complete:
Define
UINT SweepAndImage(LPVOID pParam)
Call it like
AfxBeginThread(SweepAndImage, NULL);
Instead of return 0, use
AfxEndThread(0, TRUE); /* or (1, ...) for return 1 */
to exit SweepAndImage

Making a music player in C++/GTK

I would like to create a music player, but I'm working with robots.
My robot should play a series of action (speech, move, etc) and I need to be able to stop it at anytime (for security).
I'm working with C++ and GTK.
I have a PLAY button linked to the function play_playlist:
void play_playlist ()
{
std::deque<history_record>::iterator it = list_to_play_.begin();
while (!g_stop_ && it != list_to_play_.end())
{
play_action(it); // take time to execute (simulate using sleep 3sec)
it++;
}
}
And a STOP button linked to the function set_stop_to_false:
void set_stop_to_true()
{
g_stop_ = true;
}
When I click PLAY the GUI freezes and I'm not able to click on STOP.
How can I have my playlist running and be able to click on the GUI? (i.e. GUI should be responsive)
My best hope is a thread, but I'm not sure how to use it appropriately.
When I click PLAY the GUI freezes and I'm not able to click on STOP.
You need to build a multi-threaded application. Your interface freezes because your application is busy doing something else, so not only that events raised from GUI are not being processed but they are not even raised.
Your application should start a worker thread that will do its job in the background, the main thread can then communicate with this worker thread for example via shared memory.
Once you enter a callback like play_playlist, the GTK main loop can't process events until you exit that function, which freezes the user interface. As play_action takes seconds to run, you only have 2 choices:
split play_playlist execution in several smaller steps, and use a
state machine to execute each step one after the other using a
callback triggered by g_idle_add. Here's an example of this
technique for lazy loading.
the other solution is to run your blocking play_action in a thread. Give a look at GThread. You start your thread when you press PLAY and stop it when you press STOP. However, you can't manipulate the user interface from a thread, GTK is not thread safe. Every GTK action should be processed from the main thread.