locked
Do we need to call DeleteTimerQueueTimer in the Timer Callback ? RRS feed

  • Question

  • In timer-queue timer which is created using CreateTimerQueueTimer, When timer expires and corresponding callback function is called , After callback function execution is completed, will OS take care of removing this timer from Timer Queue and perform corresponding cleanup ? or do we need to explicitly call DeleteTimerQueueTimer to remove this timer from timer queue and perform cleanup.

    If we need to explicitly call the API DeleteTimerQueueTimer,  then is it fine to call this API in the timer callback function.

    Thursday, July 31, 2014 11:05 AM

Answers

  • Hi,

    We need to call DeleteTimerQueueTimer to remove this timer from timer queue.

    We can have a look at the CreateTimerQueueTimer function.

    BOOL WINAPI CreateTimerQueueTimer(
      _Out_     PHANDLE phNewTimer,
      _In_opt_  HANDLE TimerQueue,
      _In_      WAITORTIMERCALLBACK Callback,
      _In_opt_  PVOID Parameter,
      _In_      DWORD DueTime,
      _In_      DWORD Period,
      _In_      ULONG Flags
    );

    And note its first parameter phNewTimer. It is a pointer to a buffer that receives a handle to the timer-queue timer on return. When this handle has expired and is no longer required, release it by calling DeleteTimerQueueTimer.

    Then, please check the document "DeleteTimerQueueTimer function".

    BOOL WINAPI DeleteTimerQueueTimer(
      _In_opt_  HANDLE TimerQueue,
      _In_      HANDLE Timer,
      _In_opt_  HANDLE CompletionEvent
    );
    CompletionEvent [in, optional]

    A handle to the event object to be signaled when the system has canceled the timer and all callback functions  have completed. This parameter can be NULL

    If this parameter is INVALID_HANDLE_VALUE, the function waits for any running timer callback functions to complete before returning.

    If this parameter is NULL, the function marks the timer for deletion and returns immediately. If the timer has already expired, the timer callback function will run to completion. However, there is no notification sent when the timer callback function has completed. Most callers should not use this option, and should wait for running timer callback functions to complete so they can perform any needed cleanup.

    So if you want to call the API in the timer callback function, please don't set the value of CompletionEvent to INVALID_HANDLE_VALUE.

    Best regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Anna Cc Tuesday, August 5, 2014 1:26 AM
    Friday, August 1, 2014 7:30 AM
  • Hi,

    In addition, here is the sample code for your reference.

    #include <windows.h> 
    
    #include <stdio.h> 
    
     
    
    HANDLE gDoneEvent; 
    
     
    
    VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) 
    
    { 
    
    if (lpParam == NULL) 
    
     { 
    
     printf("TimerRoutine lpParam is NULL\n"); 
    
     } 
    
    else 
    
     { 
    
    // lpParam points to the argument; in this case it is an int 
    
     
    
     printf("Timer routine called. Parameter is %d.\n", 
    
     *(int*)lpParam); 
    
    if(TimerOrWaitFired) 
    
     { 
    
     printf("The wait timed out.\n"); 
    
     } 
    
    else 
    
     { 
    
     printf("The wait event was signaled.\n"); 
    
     } 
    
     } 
    
     
    
     SetEvent(gDoneEvent); 
    
    } 
    
     
    
    int main() 
    
    { 
    
     HANDLE hTimer = NULL; 
    
     HANDLE hTimerQueue = NULL; 
    
    int arg = 123; 
    
     
    
    // Use an event object to track the TimerRoutine execution 
    
     gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
    
    if (NULL == gDoneEvent) 
    
     { 
    
     printf("CreateEvent failed (%d)\n", GetLastError()); 
    
    return 1; 
    
     } 
    
     
    
    // Create the timer queue. 
    
     hTimerQueue = CreateTimerQueue(); 
    
    if (NULL == hTimerQueue) 
    
     { 
    
     printf("CreateTimerQueue failed (%d)\n", GetLastError()); 
    
    return 2; 
    
     } 
    
     
    
    // Set a timer to call the timer routine in 10 seconds. 
    
    if (!CreateTimerQueueTimer( &hTimer, hTimerQueue, 
    
     (WAITORTIMERCALLBACK)TimerRoutine, &arg , 10000, 0, 0)) 
    
     { 
    
     printf("CreateTimerQueueTimer failed (%d)\n", GetLastError()); 
    
    return 3; 
    
     } 
    
     
    
    // TODO: Do other useful work here  
    
     
    
     printf("Call timer routine in 10 seconds...\n"); 
    
     
    
    // Wait for the timer-queue thread to complete using an event  
    
    // object. The thread will signal the event at that time. 
    
     
    
    if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0) 
    
     printf("WaitForSingleObject failed (%d)\n", GetLastError()); 
    
     
    
     CloseHandle(gDoneEvent); 
    
     
    
    // Delete all timers in the timer queue. 
    
    if (!DeleteTimerQueue(hTimerQueue)) 
    
     printf("DeleteTimerQueue failed (%d)\n", GetLastError()); 
    
     
    
    return 0; 
    
    } 
    
    Best regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Anna Cc Tuesday, August 5, 2014 1:26 AM
    Friday, August 1, 2014 7:31 AM

All replies

  • Hi,

    We need to call DeleteTimerQueueTimer to remove this timer from timer queue.

    We can have a look at the CreateTimerQueueTimer function.

    BOOL WINAPI CreateTimerQueueTimer(
      _Out_     PHANDLE phNewTimer,
      _In_opt_  HANDLE TimerQueue,
      _In_      WAITORTIMERCALLBACK Callback,
      _In_opt_  PVOID Parameter,
      _In_      DWORD DueTime,
      _In_      DWORD Period,
      _In_      ULONG Flags
    );

    And note its first parameter phNewTimer. It is a pointer to a buffer that receives a handle to the timer-queue timer on return. When this handle has expired and is no longer required, release it by calling DeleteTimerQueueTimer.

    Then, please check the document "DeleteTimerQueueTimer function".

    BOOL WINAPI DeleteTimerQueueTimer(
      _In_opt_  HANDLE TimerQueue,
      _In_      HANDLE Timer,
      _In_opt_  HANDLE CompletionEvent
    );
    CompletionEvent [in, optional]

    A handle to the event object to be signaled when the system has canceled the timer and all callback functions  have completed. This parameter can be NULL

    If this parameter is INVALID_HANDLE_VALUE, the function waits for any running timer callback functions to complete before returning.

    If this parameter is NULL, the function marks the timer for deletion and returns immediately. If the timer has already expired, the timer callback function will run to completion. However, there is no notification sent when the timer callback function has completed. Most callers should not use this option, and should wait for running timer callback functions to complete so they can perform any needed cleanup.

    So if you want to call the API in the timer callback function, please don't set the value of CompletionEvent to INVALID_HANDLE_VALUE.

    Best regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Anna Cc Tuesday, August 5, 2014 1:26 AM
    Friday, August 1, 2014 7:30 AM
  • Hi,

    In addition, here is the sample code for your reference.

    #include <windows.h> 
    
    #include <stdio.h> 
    
     
    
    HANDLE gDoneEvent; 
    
     
    
    VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired) 
    
    { 
    
    if (lpParam == NULL) 
    
     { 
    
     printf("TimerRoutine lpParam is NULL\n"); 
    
     } 
    
    else 
    
     { 
    
    // lpParam points to the argument; in this case it is an int 
    
     
    
     printf("Timer routine called. Parameter is %d.\n", 
    
     *(int*)lpParam); 
    
    if(TimerOrWaitFired) 
    
     { 
    
     printf("The wait timed out.\n"); 
    
     } 
    
    else 
    
     { 
    
     printf("The wait event was signaled.\n"); 
    
     } 
    
     } 
    
     
    
     SetEvent(gDoneEvent); 
    
    } 
    
     
    
    int main() 
    
    { 
    
     HANDLE hTimer = NULL; 
    
     HANDLE hTimerQueue = NULL; 
    
    int arg = 123; 
    
     
    
    // Use an event object to track the TimerRoutine execution 
    
     gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
    
    if (NULL == gDoneEvent) 
    
     { 
    
     printf("CreateEvent failed (%d)\n", GetLastError()); 
    
    return 1; 
    
     } 
    
     
    
    // Create the timer queue. 
    
     hTimerQueue = CreateTimerQueue(); 
    
    if (NULL == hTimerQueue) 
    
     { 
    
     printf("CreateTimerQueue failed (%d)\n", GetLastError()); 
    
    return 2; 
    
     } 
    
     
    
    // Set a timer to call the timer routine in 10 seconds. 
    
    if (!CreateTimerQueueTimer( &hTimer, hTimerQueue, 
    
     (WAITORTIMERCALLBACK)TimerRoutine, &arg , 10000, 0, 0)) 
    
     { 
    
     printf("CreateTimerQueueTimer failed (%d)\n", GetLastError()); 
    
    return 3; 
    
     } 
    
     
    
    // TODO: Do other useful work here  
    
     
    
     printf("Call timer routine in 10 seconds...\n"); 
    
     
    
    // Wait for the timer-queue thread to complete using an event  
    
    // object. The thread will signal the event at that time. 
    
     
    
    if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0) 
    
     printf("WaitForSingleObject failed (%d)\n", GetLastError()); 
    
     
    
     CloseHandle(gDoneEvent); 
    
     
    
    // Delete all timers in the timer queue. 
    
    if (!DeleteTimerQueue(hTimerQueue)) 
    
     printf("DeleteTimerQueue failed (%d)\n", GetLastError()); 
    
     
    
    return 0; 
    
    } 
    
    Best regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Anna Cc Tuesday, August 5, 2014 1:26 AM
    Friday, August 1, 2014 7:31 AM
  • Thanks for your Answer Anna Cc
    Wednesday, August 6, 2014 12:53 PM