The expected timer was designed to activate code through APC. This is quite difficult to obtain due to reconnection issues, and should only be considered if you need to run code on a thread that is otherwise busy, but often enough to allow APC to work.
Timer queues are very lightweight objects; their callback works in a (cheap) thread from a thread pool. Almost always useful for periodic service.
The third way is to start the thread when the service starts and block it using WaitForSingleObject (), the timeout of which sets the period. You are waiting for an event that signals the end of service. It is very easy to move, and not the same as the timer line.
Hans passant
source share