Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I följande exempel associeras en asynkron proceduranropsfunktion (APC), även kallat en slutföranderutin, med en väntetidstimer när timern har angetts. Adressen till slutföranderutinen är den fjärde parametern till funktionen SetWaitableTimer. Den femte parametern är en tomrumspekare som du kan använda för att skicka argument till slutföranderutinen.
Slutföranderutinen körs av samma tråd som anropade SetWaitableTimer. Den här tråden måste vara i ett aviseringsbart tillstånd för att köra slutföranderutinen. Det åstadkommer detta genom att anropa funktionen SleepEx, som är en aviseringsbar funktion.
Varje tråd har en APC-kö. Om det finns en post i trådens APC-kö när en av de aviseringsbara funktionerna anropas, kommer tråden inte att försättas i viloläge. I stället tas posten bort från APC-kön och slutföranderutinen anropas.
Om det inte finns någon post i APC-kön suspenderas tråden tills väntan är över. Väntan kan tillgodoses genom att lägga till en post i APC-kön, genom en timeout eller genom att ett handtag blir markerat. Om väntan uppfylls av en post i APC-kön aktiveras tråden och slutföranderutinen anropas. I det här fallet är funktionens returvärde WAIT_IO_COMPLETION.
När slutföranderutinen har körts söker systemet efter en annan post i APC-kön som ska bearbetas. En aviseringsbar funktion kommer att återvända först efter att alla APC-poster har bearbetats. Om poster läggs till i APC-kön snabbare än de kan bearbetas är det därför möjligt att ett anrop till en aviseringsbar funktion aldrig returneras. Detta är särskilt möjligt med väntetider, om perioden är kortare än den tid som krävs för att köra slutföranderutinen.
När du använder en väntetidstimer med en APC bör tråden som anger timern inte vänta på timerns handtag. På så sätt skulle du få tråden att väckas till följd av att timern blir signalerad snarare än till följd av att en post läggs till i APC-kön. Därför är tråden inte längre i ett aviseringsbart tillstånd och slutföranderutinen anropas inte. I följande kod vaknar anropet till SleepEx tråden när en post läggs till i trådens APC-kö efter att timern har angetts till det signalerade tillståndet.
#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;
}
Relaterade ämnen