Idle Loop Processing

Many applications perform lengthy processing "in the background." Sometimes performance considerations dictate using multithreading for such work. Threads involve extra development overhead, so they are not recommended for simple tasks like the idle-time work that MFC does in the OnIdle function. This article focuses on idle processing. For more information about multithreading, see Multithreading Topics.

Some kinds of background processing are appropriately done during intervals that the user is not otherwise interacting with the application. In an application developed for the Microsoft Windows operating system, an application can perform idle-time processing by splitting a lengthy process into many small fragments. After processing each fragment, the application yields execution control to Windows using a PeekMessage loop.

This article explains two ways to do idle processing in your application:

  • Using PeekMessage in MFC's main message loop.

  • Embedding another PeekMessage loop somewhere else in the application.

PeekMessage in the MFC Message Loop

In an application developed with MFC, the main message loop in the CWinThread class contains a message loop that calls the PeekMessage Win32 API. This loop also calls the OnIdle member function of CWinThread between messages. An application can process messages in this idle time by overriding the OnIdle function.

Note

Run, OnIdle, and certain other member functions are now members of class CWinThread rather than of class CWinApp. CWinApp is derived from CWinThread.

For more information about performing idle processing, see OnIdle in the MFC Reference.

PeekMessage Elsewhere in Your Application

Another method for performing idle processing in an application involves embedding a message loop in one of your functions. This message loop is very similar to MFC's main message loop, found in CWinThread::Run. That means such a loop in an application developed with MFC must perform many of the same functions as the main message loop. The following code fragment demonstrates writing a message loop that is compatible with MFC:

BOOL bDoingBackgroundProcessing = TRUE;
while (bDoingBackgroundProcessing)
{
   MSG msg;
   while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
   {
      if (!AfxGetApp()->PumpMessage())
      {
         bDoingBackgroundProcessing = FALSE;
         ::PostQuitMessage(0);
         break;
      }
   }
   // let MFC do its idle processing
   LONG lIdle = 0;
   while (AfxGetApp()->OnIdle(lIdle++))
      ;
   // Perform some background processing here 
   // using another call to OnIdle
}

This code, embedded in a function, loops as long as there is idle processing to do. Within that loop, a nested loop repeatedly calls PeekMessage. As long as that call returns a nonzero value, the loop calls CWinThread::PumpMessage to perform normal message translation and dispatching. Although PumpMessage is undocumented, you can examine its source code in the ThrdCore.Cpp file in the \atlmfc\src\mfc directory of your Visual C++ installation.

Once the inner loop ends, the outer loop performs idle processing with one or more calls to OnIdle. The first call is for MFC's purposes. You can make additional calls to OnIdle to do your own background work.

For more information about performing idle processing, see OnIdle in the MFC Library Reference.

See also

General MFC Topics