For Win16 programs, Windows implemented co-operative multitasking. Its implementation was based upon the "message loop" architecture of every Windows program.
The duty of every program was to endlessly run in a loop in which a call to the
GetMessage function was performed. This function call looks whether a message to this process is in the queue. If there is one, it is retrieved (
GetMessage), optionally translated (
TranslateMessage, done to convert keyboard shortcuts into menu actions) and finally, passed to the window procedure (
If there is no message available in the queue, Windows suspends the current task and gives the CPU to another task. This task will try to retrieve a message from its queue as well, yielding the CPU to another task if no message is present and so on.
If a program needed to perform background tasks while there were no pending messages in its queue, it would call
PeekMessage instead of
GetMessage. This didn't make the task relinquish the CPU, as
PeekMessage would immediately return to the caller task to inform it whether a message is available or not. This was used to time-multiplex message processing with another time-consuming task (think of a 3D program rendering but letting the user cancel that render by pressing a "Cancel" button).
If this time-consuming task was actually very time-consuming, a well-behaved program should call the
Yield function from time to time, to relinquish the CPU and let other tasks run.
A badly-behaved program could easily hog the CPU by not retrieving messages too often or by spending too much time in a window procedure function.
The situation was quite different for MS-DOS boxes. They ran using the V8086 mode of the 80386 (if Windows was running in enhanced mode). Windows-aware programs ran in the so-called System VM (Virtual Machine 1). DOS boxes ran from VM 2 upwards.
DOS programs usually were badly-behaved programs, so Windows assigned each DOS box a different virtual machine. Virtual machines used pre-emptive multitasking in Windows 3.1, so each DOS box could run concurrently to others and to any Windows-aware program.