But what I want to know is what is this "yield" functionality, is it
a Windows API function that a process must call in multiple places
in the process's code?
You mostly never need to call Yield().
Under normal circumstances you just handle the
requested WM message and exit from the window
procedure, and the control is then transferred
to other tasks. Your procedure will be called
again once there is a message for it to handle.
Now sometimes you need to perform the "blocking"
operation, during which you can't return. Here
you seemingly have a choice: either you call Yield()
periodically, or you run this code:
ret = (BOOL) PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
/* if we got one, process it */
if (ret) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
PeekMessage() also yields.
So now the question is: why to write as much code, if
I can just call Yield()? And the answer is: no, you
actually can't. Don't use Yield().
The problem with Yield() is that actually it only switches
to another task(s) if they have any messages to process.
If they don't - Yield() returns immediately, so you
may end up calling it in a busy loop. PeekMessage() AFAIK
also adds some "sleep" if there are no messages, so it is
already much better that Yield(). But the real culprit is
in DispatchMessage(). Its a synchronous dispatcher that
calls directly into the window procedure that is supposed to
handle this message. And the most important thing here is
that this may even be your own window procedure! The same
one that does the blocking operation. Yield() never results
in a recursive calls into your own window procedure, because
the windows' scheduler knows it haven't returned yet, so it
won't call it. Only the direct call with DispatchMessage()
allows your window procedure to be recursively called, to
handle all other events, like timers, redraw events etc.
So that way your app stays alive while blocking. With just
Yield(), at best only other apps stay alive, and at worst -
you just call it in a busy loop.