Timers are essential to multimedia and animation applications. Good animation depends on timer accuracy and synchronization between multiple time-dependent components. Developers can use the Microsoft Timer API to synchronize time-dependent components such as audio and video clips.
Timers are necessary for many operations. For example, they are commonly used:
- By single-threaded components to do background processing on the main user interface thread.
- By applications when an external source must be polled, or the rate of change of a control is unknown. In these cases, developers use periodic timers to check for change or new data.
- By developers to synchronize real-time computer animation.
The following topics are discussed in this article.
The Timer API was created to address problems with currently available timers. For example, Windows provides timers that developers can use even for windowless controls. However, Windows timers are not as accurate as applications may require. Although Windows timer messages can be scheduled with millisecond accuracy, they seldom deliver that result because the accuracy of a Windows timer is dependent on the system clock and current activity. Because WM_TIMER messages are processed at a low priority, somewhat like WM_PAINT messages, they are often delayed while other messages are processed.
Computer clocks are just as problematic. All computer devices rely on high-resolution quartz clock chips to keep time. Although these chips are accurate, they are not consistent across all hardware. For example, sound cards may vary in speed by as much as 7 percent. This means that playing a five-second audio clip may require more or less than five seconds. If there is a soundtrack for the animation or video, poor synchronization may be noticed.
To overcome these timer problems, the MSHTML Timer API is implemented as a service. Through this service, clients can create multiple timer objects and receive callbacks. Also, they can retrieve the same timer for various controls, ensuring that all the timers behave alike. MSHTML supports named timers, which enable controls to access a particular timer. When you create a timer you can register a name and pass that name to methods such as ITimerService::GetNamedTimer.
The MSHTML timer implementation consolidates all top-level timer requests into a single low-level scheduler, known as a base timer. The base timer runs on the main user interface thread. The base timer itself is driven by the timer source on a different thread. The MSHTMLreference timer invokes the base timer through a PostMessage, not a WM_TIMER message, to the user interface thread.
The MSHTML reference timer uses low-level operating system functions to generate time events. However, because developers can provide alternative reference timers, it is possible to use an external time source such as an audio and video playback component. This ensures that the entire system stays in sync with external media. Timers can have their reference timer switched at any time, eliminating any potential problems with the availability of a reference timer. Reference timers may also be used to provide debugging support by stepping through timer callbacks one at a time.
Local synchronization is achieved by allowing the clock to be temporarily frozen. This can be done explicitly from a control or a script, or implicitly by the container. The container freezes the clock when it is painting or when servicing several callbacks at the same time.
Controls or scripts freeze the clock when executing actions that have timed behavior. For example, if a script needs to start a video and an audio clip simultaneously, it should freeze the clock, issue the commands, and then restart the clock.
When the clock is frozen, the reported time stops changing and callbacks are suspended. This ensures that all clients of a particular clock see the same virtual instant in time.