Contents:
- 1 Thread Pooling
- 2 Scenario 1: Call Functions Asynchronously
<? 1> Thread pool components and their behavior
| Component |
|
Timer |
Wait |
I/O |
Non-I/O |
| Initial Number of Threads |
Always 1 |
1 |
0 |
0 |
| When a Thread Is Created |
When first thread pool timer function is called |
One thread for every 63 registered objects |
The system uses heuristics, but here are some factors that affect the creation of a thread:
- Some time (in seconds) has passed since the threads as added
- The WT_EXECUTELONGFUNCTION flag is used
- The number of queued work items exceeds a certain threshold
|
| When a Thread is Destroyed |
When a process terminates |
When the number of registered wait objects is 0 |
When the thread has no pending I/O requests and has been idle for a threshold period (about a minute) |
When the thread is idle for a threshold period (about a minute) |
| How a Thread Waits |
Alertable |
WaitForMultipleObjectsEx |
Alertable |
GetQueuedCompletionStatus |
| What Wakes Up a Thread |
Waitable timer is signaled queuing a user APC |
Kernal object becomes signaled |
Queued user APC or completed I/O request |
Posted completion status or completed I/O request (The completion port allows at most 2 * number of CPUs threads to run concurrently) |
2 Scenario 1: Call Functions Asynchronously #
BOOL QueueUserWorkItem(
PTHREAD_START_ROUTINE pfnCallback,
PVOID pvContext,
ULONG dwFlags
);
DWORD WINAPI WorkItemFunc( PVOID pvContext );
3 Scenario 2: Call Functions at Timed Intervals #
HANDLE CreateTimerQueue();
BOOL CreateTimerQueueTimer(
PHANDLE phNewTimer,
HANDLE hTimerQueue,
WAITORTIMERCALLBACK pfnCallback,
PVOID pvContext,
DWORD dwDueTime,
DWORD dwPeriod,
ULONG dwFlags
);
VOID WINAPI WaitOrTimerCallback(
PVOID pvContext,
BOOL fTimerOrWaitFired
);
BOOL DeleteTimerQueueTimer(
HANDLE hTimerQueue,
HANDLE hTimer,
HANDLE hCompletionEvent
);
BOOL ChangeTimerQueueTimer(
HANDLE hTimerQueue,
HANDLE hTimer,
ULONG dwDueTime,
ULONG dwPeriod
);
BOOL DeleteTimerQueueEx(
HANDLE hTimerQueue,
HANDLE hCompletionEvent
);
3.1 The TimedMsgBox Sample Application #
TimedMsgBox.cpp
/******************************************************************************
Module: TimedMsgBox.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/
#include "..\CmnHdr.h" /* See Appendix A. */
#include <tchar.h>
//////////////////////////////////////////////////////////////////////////////
// The caption of our message box
TCHAR g_szCaption[] = TEXT( "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, TEXT( "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 );
}
} else {
// The window does not exist yet; do nothing this time.
// We'll try again in another second.
}
}
//////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain( HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int )
{
chWindows9xNotAllowed();
// How many seconds we'll give the user to respond
g_nSecLeft = 10;
// Create a multishot 1-second timer that begins firing after 1 second.
HANDLE hTimerQTimer;
CreateTimerQueueTimer( &hTimerQTimer, NULL, MsgBoxTimeout, NULL,
1000, 1000, 0 );
// Display the message box.
MessageBox( NULL, TEXT( "You have 10 seconds to respond" ),
g_szCaption, MB_OK );
// Cancel the timer & delete the timer queue
DeleteTimerQueueTimer( NULL, hTimerQTimer, NULL );
// Let us know if the user responded or if we timed out.
MessageBox(NULL,
( g_nSecLeft == 0 ) ? TEXT( "Timeout" ) : TEXT( "User responded" ),
TEXT( "Result" ), MB_OK );
return ( 0 );
}
//////////////////////////////// End of File /////////////////////////////////
TimedMsgBox.rc
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_TIMEDMSGBOX ICON DISCARDABLE "TimedMsgBox.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
4 Scenario 3: Call Functions When Single Kernel Objects Become Signaled #
BOOL RegisterWaitForSingleObject(
PHANDLE phNewWaitObject,
HANDLE hObject,
WAITORTIMERCALLBACK pfnCallback,
PVOID pvContext,
ULONG dwMilliseconds,
ULONG dwFlags
);
VOID WINAPI WaitOrTimerCallbackFunc(
PVOID pvContext,
BOOLEAN fTimerOrWaitFired
);
BOOL UnregisterWaitEx(
HANDLE hWaitHandle,
HANDLE hCompletionEvent
);
5 Scenario 4: Call Functions When Asynchronous I/O Requests Complete #
BOOL BindIoCompletionCallback(
HANDLE hDevice,
POVERLAPPED_COMPLETION_ROUTINE pfnCallback,
ULONG dwFlags
);
VOID WINAPI OverlappedCompletionRoutine(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransferred,
POVERLAPPED pOverlapped
);
CategoryTranslation