roger's picture

Things I learnt this week: SetWaitableTimer

SetWaitableTimer doesn't accept NULL for the pDueTime parameter. It returns FALSE; GetLastError() returns ERROR_NOACCESS (998). If you specify zero (i.e. a LARGE_INTEGER containing zero) for pDueTime, the timer is signalled immediately.

There are 10,000,000 FILETIME units (100ns) in a second. There are 10,000 FILETIME units (100ns) in a millisecond. Something like this might come in useful:

const LONGLONG FILETIME_UNITS_PER_MICROSECOND = 10;
const LONGLONG FILETIME_UNITS_PER_MILLISECOND = FILETIME_UNITS_PER_MICROSECOND * 1000;
const LONGLONG FILETIME_UNITS_PER_SECOND = FILETIME_UNITS_PER_MILLISECOND * 1000;

LARGE_INTEGER WaitableTimerDelayFromMilliseconds(LONG milliseconds)
{
   LARGE_INTEGER li;
   li.QuadPart = 0 - (milliseconds * FILETIME_UNITS_PER_MILLISECOND);
   return li;
}

If you set the timer to auto-reset, it will tick on the period. If you set the timer to manual-reset, it will tick once, and then stay signalled. You can't use ResetEvent to reset a manual-reset timer; it will return FALSE, GetLastError() returns ERROR_INVALID_HANDLE (6).

To reset a manual-reset timer, you need to use SetWaitableTimer, which requires that you pass in another initial delay. If you pass in zero, you get the same behaviour as above.

This means, realistically, that you can't use a periodic timer with a manual-reset timer. Which makes sense, but I've never seen it spelt out anywhere.

Reply

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <b> <br> <code> <dd> <dl> <dt> <hr> <h1> <h2> <h3> <i> <img> <li> <ol> <p> <pre> <table> <td> <th> <tr> <tt> <u> <ul>
  • Images can be added to this post.

More information about formatting options