If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Do other things whilst in a loop

Hi, newbie here, still very much learning.

I'm writing a piece of software in MFC. In one function, I have a while loop using "KeepLooping" as the condition.

"KeepLooping" is a boolean that is set to false by a toolbar button, key press or menu option. The problem is, when the loop starts running, its obviously so busy in the loop that button presses, toolbar buttons and menu clicks do nothing, so the loop never exits.

What's the best (or should that be simplest?) way around this? I remember in VB you could rather crudely just use DoEvents in a loop to make sure it carried on doing other things in the mean time, but I'm guessing its not that simple in C++.

Re: Do other things whilst in a loop

Originally Posted by nnXen

What's the best (or should that be simplest?) way around this?

The best way around it is simply not to use "busy waiting".

All modern GUIs (and even OSes) are based on the principle of "don't call us, we call you". That is event handling objects register themselves as subscribers to the events they're interested in and then passively just hang around. Then when an even happens all its subscribers (also called listeners) get called in turn. It's considered good manners to finish as quickly and swiftly as possible not to block fellow listeners.

Read the MFC documentation and study examples to see how the event handling mechanism works.

Re: Do other things whilst in a loop

I remember in VB you could rather crudely just use DoEvents in a loop to make sure it carried on doing other things in the mean time, but I'm guessing its not that simple in C++.

With MFC it's possible, but it's a fragile solution. The better approach is to run the loop in a thread (caled a worker thread). Then you'll need to synchronize the communication between the GUI thread and the worker thread.

Re: Do other things whilst in a loop

What you need to realize about MFC (and Windows programmign in general) is that:

Whilst you are in a messagehandler function... No other messagehandlers will get called other than messages SENT from that one messagehandle.

Read that again. And once more, make sure you fully understand this, it's quite important to understand what that means.

So for example.
if you have an app, and you have a menu-item for "calculate stuff", and you have an OnCalculateStuff() function. then while that OnCalculateStuff() is happening. your UI will be blocked. It won't handle other messages, it won't even repaint itself, you can't click buttons, move the window, minimize/maximize, ...

So conceptually what you're trying to do simply won't work. because while in your "keeplooping" loop, no other messages will be processed.

There are ways around this.
The generally recommended way is using multiple threads, and have your calculations out of the GUI thread and into one or more worker threads. However, multithreading adds a whole slew of additional problems to your application such as synchronisation and making the GUI and worker thread cooperate properly. It isn't really something for a beginning programmer. Make sure you understand windows programmign properly first !

Another way around it is to process messages in your 'keep looping' loop. This is also called "pumping messages". This works, to a degree, and has some issues of itself. It's sort of a 'poor man's approach' to threading and keeping your app going. it's not without it's own perils. and your while keeplooping loop is effectively suspended for the time it is in the other messagehandlers. You'll probably also need guards against certain UI actions. if someone started the keeplooping loop via a menu. you probably want to prevent them from selecting that same menu item again.

Re: Do other things whilst in a loop

Thanks Guys! That's been a massive help. I'll probably go with the message pumping method for now but threads are certainly something I'll have to look in to for future reference as it seems that's the real way to go about it

Re: Do other things whilst in a loop

Well the message pumping method works, but it is buggy with UI updating etc. I think I need to start the loop in a thread. I've had a look through various tutorials on AfxBeginThread, but I can't for the life of me get it to work. Basically at the moment, when a toolbar button is clicked I call the function "Playback", which is basically contains a loop which continues to loop until a boolean is set to false. A simplified version of what I have is below;

Re: Do other things whilst in a loop

It reads button presses etc, but is quite buggy in that it doesn't 'raise' buttons on hover and obviously doesn't continue running the loop if a button press starts another function or opens a dialog... that's why I was thinking it's probably best to start the loop in a worker thread.

Re: Do other things whilst in a loop

It reads button presses etc, but is quite buggy in that it doesn't 'raise' buttons on hover and obviously doesn't continue running the loop if a button press starts another function or opens a dialog... that's why I was thinking it's probably best to start the loop in a worker thread.

Re: Do other things whilst in a loop

Re: Do other things whilst in a loop

Finally, if the user closes the application, how can I terminate the loop before it closes (otherwise it throws errors if the loop is still running.) I understand its the WM_CLOSE message in CMainFrame? How can I change the loop condition in CDAWView from there?

Re: Do other things whilst in a loop

Originally Posted by nnXen

Finally, if the user closes the application, how can I terminate the loop before it closes (otherwise it throws errors if the loop is still running.) I understand its the WM_CLOSE message in CMainFrame? How can I change the loop condition in CDAWView from there?

That's one of those "and has some issues of itself" I mentioned...
If your other loop can't handle being "aborted" because in the messagepump you close the app. then the only way out is to either disable close while the outer loop is running. or to delay close (signal to the outer loop that it needs to stop, and then post the close from there or something along those lines).

Neither solution is ideal, but things like that also appear in a threading approach. Closing the main GUI thread, terminates worker threads so unless you guard against that and allow worker threads to properly shut down, you have a similar issue there as well.

If you're programmign in MFC, there is another approach to do stuff "in the background" and that's working with the OnIdle() message handler in the app object. It does mean you need to change your "loop" into separated small chunks of work though, and do a small bit of work each OnIdle call. It's an easy solution for some forms of background processing, but it's not a fit-all-problems thing either.

* The Perfect Platform for Game Developers: Android
Developing rich, high performance Android games from the ground up is a daunting task. Intel has provided Android developers with a number of tools that can be leveraged by Android game developers.

* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.