A timer is a kernel object that is fired at a specific time or at regular intervals. Asynchronous program calls that combine timers allow callback functions to be executed when any timer is fired. The example code in this article shows how to implement it.
When using this timer, you need to define the constant _win32_winnt as 0x0400, and this constant should be defined before the package to ensure that the appropriate timer prototype function is declared.
You can create a timer by calling CreateWaitableTimer (), which returns a handle to the kernel object. If the timer already exists, you can get a process-related handle by using Openwaitabletimer (). Either through the CreateWaitableTimer () or the handle obtained through Openwaitabletimer (), you must release the timer without the need for it, using the function CloseHandle ().
The timed time is set by calling SetWaitableTimer (), which can be set to a specific moment (such as December, 1999 at 9:45 PM) or a relative time (such as every five minutes from now). function setwaitabletime () Timing parameter requires Large_integer type. This value should conform to the format described in the filetime of the struct body. If the value is positive, it represents a particular moment. If the value is negative, it represents the relative time in 100 nanoseconds. A relative time is used in the following sample code. After the SetWaitableTimer () function is invoked, the timer is fired once every 5 seconds.
You can also set the timer to be a periodic self excitation by passing a periodic parameter (in milliseconds) to the third parameter of SetWaitableTimer (). Passing false in the second parameter of CreateWaitableTimer () can produce an automatic zero-zeroing timer. This example sets a timer with a period of two seconds.
When the timer is set, you can combine the APC with it. This refers to the APC function as a complete routine. The address of the complete routine is the fourth parameter of the SetWaitableTimer (). The fifth parameter is a pointer to an empty type that you can use to pass the parameters of the complete routine.
In all APC, the thread must be in a listening state to perform a complete routine. The complete routine will always be executed by the same thread that calls SetWaitableTimer (), so this thread must put itself in a listening state. You can call any of the following listening functions to complete the setting of the listening state:
SleepEx ();
WaitForSingleObjectEx ();
WaitForMultipleObjectsEx ();
Msgwaitformultipleobjectsex ();
SignalObjectAndWait ();
Any one of the threads has an APC queue. When you call any of the above functions, if there is an entity in the APC queue for the thread, the thread does not go into hibernation, instead it takes the entity out of the APC queue and then calls the corresponding complete routine.
If no entity exists in the APC queue, the thread will be suspended until the waiting condition is satisfied. The wait conditions are met: An entity joins the APC queue, timeouts, activates a handle, and so on, and a message enters a message queue in the thread when Msgwaitformultipleobjectsex () is invoked. If the wait condition satisfies an entity in the APC queue, the thread is activated and a complete routine is executed, in which case the return value of the function is wait_io_completion.
"Important Tips"
1. After performing a complete routine, the system examines the remaining entities in the APC to process. A monitoring function returns only after all APC entities have been processed. Therefore, calling these functions may never return if the entities are added to the APC queue faster than they are processed. This situation is more likely to occur especially if the timing of the wait is shorter than the time required to perform a complete routine.