[comp.windows.ms.programmer] Cooperative Multitasking?

jan@prisma.cv.ruu.nl (Jan Buitenhuis) (01/04/91)

Hi,

I've run into the following problem: my application has to calculate
for some minutes. It thereby blocks Windows' (non-preemptive)
Multitasking capabilities. Is there a general way to
avoid this problem and to make such a procedure cooperative?

I gues you could write a Timer callback function. The mere 
thought of all the problems involving such a function makes
me sick.
Is it worth the bother? Will the next version of windows solve
this problem? 

Any suggestions?

Jan Buitenhuis.

bruceki@polari.UUCP (Bruce King) (01/04/91)

  Imbed a call to PeekMessage in your processing loop.  Windows will reschedule,
allowing other apps to run, or if no other app wishes to run, return control
to your program immediately.  Alternatively you can issue a call to Yield()
or GetMessage.  PeekMessage is the call of my choice though; it reschedules 
without forcing you to remove the message from the queue and deal with it.

  Bruce King / bruceki@microsoft (work) / bruceki@polari (home) 

avbalen@ehviea.ine.philips.nl (A.G.M. van Balen) (01/04/91)

In your computation loop, include something as PeekMessage,
looking for a message that will allow te user to stop the program or
abort the calculation or something

Auke

risto@tuura.UUCP (Risto Lankinen) (01/04/91)

jan@prisma.cv.ruu.nl (Jan Buitenhuis) writes:

>Hi,

>I've run into the following problem: my application has to calculate
>for some minutes. It thereby blocks Windows' (non-preemptive)
>Multitasking capabilities. Is there a general way to
>avoid this problem and to make such a procedure cooperative?

Hi!

Calling Yield() periodically during the calculation should work.  There
is, however, another way what I think adds even more functionality:

If the calculation takes that much time to complete, it would be a nice
feature, too, to let the user cancel the operation should it take too
long.  You can kill two flies in one shot by calling PeekMessage() every
now an then within the calculation loop, as below:

#define  ID_CANCELCALC  0xWHATEVER
MSG tmpMsg;
 . . .
   // Within the 'calculation loop' every once in a while do:
   if( PeekMessage(&tmpMsg,hWnd,WM_COMMAND,WMCOMMAND,PM_NOREMOVE) ) {
      if( tmpMsg.wParam==ID_CANCELCALC ) {
         // Remove {WM_COMMAND,IDCANCELCALC} from the queue with an other
         // call to the PeekMessage(,,,,PM_REMOVE), or mark it processed,
         // or refrain from processing it at all in the usual WM_COMMAND
         // case, then cancel the calculation.
      }
   }
   // Und so weiter...

Now, at the time of PeekMessage() call, the other apps have a chance to run,
and at the same time it can be checked whether the user wants to cancel the
lengthy operation.  There are a few things to take into account: 1) Memory
blocks, which aren't locked, may move depending on what the other apps will
do when they get the control, 2) your application might get a rebound call,
in which case you should keep a flag to tell whether the lengthy operation
is active (and deny restart unless so desired), and 3) the calculation will
take even longer due to the task switch overhead, although the difference
between PeekMessage() and Yield() is somewhat insignificant.

terveisin: Risto Lankinen
-- 
Risto Lankinen / product specialist ***************************************
Nokia Data Systems, Technology Dept *  2                              2   *
THIS SPACE INTENTIONALLY LEFT BLANK * 2 -1 is PRIME!  Now working on 2 +1 *
replies: risto@yj.data.nokia.fi     ***************************************