Sleeping a thread and waiting on a handle with a timeout are basically the same thing under the covers. I would guess that timers are essentially implemented using sleep, so not much difference there, either. In other words, you could simplify your code by waiting on the handle with a timeout in a single loop and checking to see why the wait was released (data available or timeout), rather than implementing separate wait and sleep loops. Slightly more efficient than independent loops.
Ideally, you would not use sleep at all and simply depend on the data-generation code to correctly raise the event your consumption code is waiting on, with a longish timeout to handle when the event source has gone away.
If the data is external, such as on a socket or other input device, then the handle can generally be set to allow waiting for data to become available - no need to poll in that case since the event will always be signaled when data is ready for consumption.