Figure 1  
Behavior of Thread Pool Components

Component
Initial # of Threads
Threads Created
Threads Destroyed
How Threads Wait
What Wakes a Thread
Timer
Always 1
When first thread pool timer function is called.
When no timer queue exists.
Alertable
Waitable timer is signaled, queuing a user APC.
Wait
1
One thread for every 63 registered objects.
When number of registered wait objects is 0.
WaitForMultiple- ObjectsEx
Kernel object becomes signaled.
I/O
0
Heuristic, but some objects that affect it include: some time has passed (in seconds) since a thread was added; a work item is queued with the WT_EXECUTELONG- FUNCTION flag; or the number of queued work items exceeds a threshold amount.
If the thread has no pending I/O requests and has been idle for a threshold period (a minute or so).
Alertable
Queued user APC or completed I/O request.
Non-I/O
0
Same as I/O.
If idle for a threshold period (a minute or so).
GetQueuedCom pletionStatus
Posted completion status or completed I/O request. The completion port allows at most (2 X the number of CPUs) threads to run concurrently.


Figure 2   A Timed Message Box

/************************************************************
Module name: TimedMsgBox.cpp
Notices: Written 1999 by Jeffrey Richter
************************************************************/

#define STRICT
#define _WIN32_WINNT 0x0500
#include <windows.h>

/////////////////////////////////////////////////////////////

// The caption of our message box
char g_szCaption[] = "Timed Message Box";

// How many seconds we'll display the message box
int g_nSecLeft = 0;

// This is STATIC window control ID for a message box
#define ID_MSGBOX_STATIC_TEXT    0x0000ffff

/////////////////////////////////////////////////////////////

VOID WINAPI MsgBoxTimeout(PVOID pvContext, BOOLEAN fTimeout) {

   // NOTE: Due to a thread race condition, it is possible 
   // (but very unlikely) that the message box will not be 
   // created when we get here.
   HWND hwnd = FindWindow(NULL, g_szCaption);

   if (hwnd != NULL) {
      // The window does exist, update the time remaining.
      TCHAR sz[100];
      wsprintf(sz, "You have %d seconds to respond", g_nSecLeft--);
      SetDlgItemText(hwnd, ID_MSGBOX_STATIC_TEXT, sz);


      if (g_nSecLeft == 0) {
         // The time is up, force the message box to exit
         EndDialog(hwnd, IDOK);
      }
   }
}

/////////////////////////////////////////////////////////////

int WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int) {

   // How many seconds we'll give the user to respond
   g_nSecLeft = 10;

   // Create a multi-shot 1 second timer which begins firing after 1 second.
   HANDLE hTimerQTimer;
   CreateTimerQueueTimer(&hTimerQTimer, NULL, 
      MsgBoxTimeout, NULL, 1000, 1000, 0);

   // Display the message box
   int n = MessageBox(NULL, "You have 10 seconds to respond", 
      g_szCaption, MB_OK);

   // Cancel the timer & delete the timer queue
   BOOL f = DeleteTimerQueueTimer(hTimerQ, hTimerQTimer, NULL);

   // Let us know if the user responded or if we timed-out.
   MessageBox(NULL, (g_nSecLeft == 0) ? "Timeout" : "User responded"), 
              "Result", MB_OK);

   return(0);
}

//////////////////////// End Of File ////////////////////////