Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Contoh berikut mengaitkan fungsi panggilan prosedur asinkron (APC), juga dikenal sebagai rutinitas penyelesaian, dengan timer yang dapat ditunggu saat timer diatur. Alamat rutinitas penyelesaian adalah parameter keempat untuk fungsiSetWaitableTimer. Parameter kelima adalah penunjuk kekosongan yang dapat Anda gunakan untuk meneruskan argumen ke rutinitas penyelesaian.
Rutinitas penyelesaian akan dijalankan oleh utas yang sama yang memanggil SetWaitableTimer. Utas ini harus dalam status yang dapat diperingatkan untuk menjalankan rutinitas penyelesaian. Ini mencapainya dengan memanggil fungsi SleepEx , yang merupakan fungsi yang dapat diperingatkan.
Setiap utas memiliki antrean APC. Jika ada entri dalam antrean APC utas pada saat salah satu fungsi yang dapat menerima sinyal peringatan dipanggil, utas tidak diistirahatkan. Sebagai gantinya, entri dihapus dari antrean APC dan prosedur penyelesaian dipanggil.
Jika tidak ada entri dalam antrean APC, utas digantung sementara hingga penantian terpenuhi. Penantian dapat dipenuhi dengan menambahkan entri ke antrean APC, dengan batas waktu, atau dengan handel yang menjadi sinyal. Jika penantian terpenuhi oleh entri dalam antrean APC, utas terbangun dan rutinitas penyelesaian dipanggil. Dalam hal ini, nilai pengembalian fungsi WAIT_IO_COMPLETION.
Setelah rutinitas penyelesaian dijalankan, sistem memeriksa entri lain dalam antrean APC untuk diproses. Fungsi yang dapat memberikan peringatan akan kembali hanya setelah semua entri APC diproses. Oleh karena itu, jika entri ditambahkan ke antrean APC lebih cepat daripada yang dapat diproses, ada kemungkinan bahwa panggilan ke fungsi yang dapat diperingatkan tidak akan pernah kembali. Ini terutama dimungkinkan dengan timer yang dapat ditunggu, jika periode lebih pendek dari jumlah waktu yang diperlukan untuk menjalankan rutinitas penyelesaian.
Saat Anda menggunakan timer yang dapat ditunggu dengan APC, utas yang mengatur timer tidak boleh menunggu pada handle timer. Dengan demikian, Anda akan menyebabkan utas terbangun akibat timer yang memberi sinyal, bukan karena ada entri yang ditambahkan ke antrean APC. Akibatnya, utas tidak lagi dalam keadaan siaga dan rutinitas penyelesaian tidak dipanggil. Dalam kode berikut, panggilan ke SleepEx membangunkan utas saat entri ditambahkan ke antrean APC utas setelah timer diubah ke keadaan disinyalir.
#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;
}
Topik terkait