Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
Az alábbi példa egy aszinkron eljáráshívási (APC) függvényt, más néven befejezési rutint társít egy várakozó időzítőhöz, az időzítő beállításakor. A befejezési rutin címe a SetWaitableTimer függvény negyedik paramétere. Az ötödik paraméter egy üres mutató, amellyel argumentumokat adhat át a befejezési rutinnak.
A befejezési rutint ugyanaz a szál hajtja végre, amely SetWaitableTimernéven fut. Ennek a szálnak riasztási állapotban kell lennie a befejezési rutin végrehajtásához. Ezt úgy hajtja végre, hogy meghívja a SleepEx függvényt, amely egy riasztásra alkalmas függvény.
Minden szálhoz egy APC-sor tartozik. Ha egy bejegyzés szerepel a szál APC-üzenetsorában az egyik riasztási függvény meghívásakor, a szál nem lesz alvó állapotba helyezve. Ehelyett a rendszer eltávolítja a bejegyzést az APC-üzenetsorból, és meghívja a befejezési rutint.
Ha nincs bejegyzés az APC-üzenetsorban, a rendszer felfüggeszti a szálat, amíg a várakozás nem teljesül. A várakozást úgy lehet kielégíteni, ha egy bejegyzést ad hozzá az APC-üzenetsorhoz, időtúllépéssel vagy egy jelzéssé váló fogóponttal. Ha a várakozást az APC-üzenetsor egyik bejegyzése kielégíti, a folyamat felébred, és a befejezési rutin meghívása történik. Ebben az esetben a függvény visszatérési értéke WAIT_IO_COMPLETION.
A befejezési rutin végrehajtása után a rendszer egy másik bejegyzést keres az APC-üzenetsorban a feldolgozáshoz. A riasztható függvény csak az összes APC-bejegyzés feldolgozása után tér vissza. Ezért, ha a bejegyzések gyorsabban kerülnek az APC-üzenetsorba, mint ahogy feldolgozhatók, lehetséges, hogy egy riasztás érzékeny függvény meghívása soha nem tér vissza. Ez különösen lehetséges várakozási időzítőkkel, ha a periódus rövidebb, mint a befejezési rutin végrehajtásához szükséges idő.
Ha várakozó időzítőt használ egy APC-vel, az időzítőt beállító szálnak nem szabad várnia az időzítő fogantyújára. Ezzel azt okozhatja, hogy a szál az időzítő jelzése helyett az APC-üzenetsorhoz hozzáadott bejegyzés miatt ébred fel. Ennek eredményeképpen a szál már nem érzékeny a riasztásokra, és a befejezési rutint nem hívják meg. Az alábbi kódban a SleepEx hívása akkor ébreszti fel a szálat, amikor egy bejegyzést adnak a szál APC-üzenetsorához, miután az időzítőt a jelzett állapotra állították.
#define UNICODE 1
#define _UNICODE 1
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define _SECOND 10000000
typedef struct _MYDATA {
LPCTSTR szText;
DWORD dwValue;
} MYDATA;
VOID CALLBACK TimerAPCProc(
LPVOID lpArg, // Data value
DWORD dwTimerLowValue, // Timer low value
DWORD dwTimerHighValue ) // Timer high value
{
// Formal parameters not used in this example.
UNREFERENCED_PARAMETER(dwTimerLowValue);
UNREFERENCED_PARAMETER(dwTimerHighValue);
MYDATA *pMyData = (MYDATA *)lpArg;
_tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,
pMyData->dwValue );
MessageBeep(0);
}
int main( void )
{
HANDLE hTimer;
BOOL bSuccess;
__int64 qwDueTime;
LARGE_INTEGER liDueTime;
MYDATA MyData;
MyData.szText = TEXT("This is my data");
MyData.dwValue = 100;
hTimer = CreateWaitableTimer(
NULL, // Default security attributes
FALSE, // Create auto-reset timer
TEXT("MyTimer")); // Name of waitable timer
if (hTimer != NULL)
{
__try
{
// Create an integer that will be used to signal the timer
// 5 seconds from now.
qwDueTime = -5 * _SECOND;
// Copy the relative time into a LARGE_INTEGER.
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );
bSuccess = SetWaitableTimer(
hTimer, // Handle to the timer object
&liDueTime, // When timer will become signaled
2000, // Periodic timer interval of 2 seconds
TimerAPCProc, // Completion routine
&MyData, // Argument to the completion routine
FALSE ); // Do not restore a suspended system
if ( bSuccess )
{
for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )
{
SleepEx(
INFINITE, // Wait forever
TRUE ); // Put thread in an alertable state
}
}
else
{
printf("SetWaitableTimer failed with error %d\n", GetLastError());
}
}
__finally
{
CloseHandle( hTimer );
}
}
else
{
printf("CreateWaitableTimer failed with error %d\n", GetLastError());
}
return 0;
}
Kapcsolódó témakörök