我可以在一个控制台c++应用程序中使用SetTimer() API吗?

时间:2021-05-01 20:51:40

I have a console application that is using a DLL file that uses a SetTimer() call to create a timer and fire a function within itself. The call is below:

我有一个控制台应用程序,它使用一个DLL文件,它使用SetTimer()调用来创建计时器并在其内部触发一个函数。下面的调用:

SetTimer((HWND)NULL, 0, timer_num, (TIMERPROC)UnSyncMsgTimer)) == 0) 

It is expecting to receive timer messages, but this never happens. I assume because mine is a console application and not a standard Windows GUI application (like where the DLL file was originally used). This stops a key part of the DLL files functionality from working.

它希望接收定时器消息,但这从来没有发生过。我假定是因为我的是一个控制台应用程序,而不是一个标准的Windows GUI应用程序(比如最初使用DLL文件的地方)。这将停止DLL文件功能的关键部分。

My application needs to stay a console application, and I cannot change the DLL.

我的应用程序需要保留一个控制台应用程序,而我不能更改DLL。

Is there a work around to make this work?

有什么工作可以做吗?

6 个解决方案

#1


9  

You can use CreateTimerQueueTimer function

您可以使用CreateTimerQueueTimer函数。

HANDLE timer_handle_;
CreateTimerQueueTimer(&timer_handle_, NULL, TimerProc, user_object_ptr, 10, 0, WT_EXECUTEDEFAULT);
//callback
void TimerProc(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    user_object* mgr = (user_object*) lpParameter;
    mgr->do();
    DeleteTimerQueueTimer(NULL, timer_handle_, NULL);
    timer_handle_ = NULL;
}

#2


5  

Timers set using the SetTimer API require a Windows message processing function to be actively running, as that is where the time messages are sent.

使用SetTimer API设置的计时器需要一个Windows消息处理函数来运行,因为这是发送时间消息的地方。

If you need a timer thread then you could register a Window class and create a default window message pump (See this article for a short example), but a simpler process would probably be to just spin up a second thread to handle your timing events and send notifications.

如果您需要一个计时器线程,那么您可以注册一个窗口类并创建一个默认的窗口消息源(请参阅本文的一个简短示例),但是一个更简单的过程可能是仅仅创建第二个线程来处理您的计时事件并发送通知。

#3


4  

Have a look at the following example which shows how to use WM_TIMER messages with a console app:

下面的示例展示了如何使用一个控制台应用程序使用WM_TIMER消息:

(Credit to the simplesamples.info site)

(归功于simplesamples.info网站)

#define STRICT 1 
#include <windows.h>
#include <iostream.h>

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) {
  cout << "Time: " << dwTime << '\n';
  cout.flush();
}

int main(int argc, char *argv[], char *envp[]) {
      int Counter=0;
      MSG Msg;
      UINT TimerId = SetTimer(NULL, 0, 500, &TimerProc);

      cout << "TimerId: " << TimerId << '\n';
      if (!TimerId)
        return 16;
      while (GetMessage(&Msg, NULL, 0, 0)) {
        ++Counter;
      if (Msg.message == WM_TIMER)
        cout << "Counter: " << Counter << "; timer message\n";
      else
        cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
      DispatchMessage(&Msg);
    }

    KillTimer(NULL, TimerId);

    return 0;
}

#4


1  

Have you considered Waitable Timers or Timer Queues? While it is possible to use SetTimer from a console app, these other facilities might be more appropriate for you.

您是否考虑过Waitable计时器或计时器队列?虽然可以从控制台应用程序使用SetTimer,但是这些其他的工具可能更适合您。

#5


1  

Using Timer Queues

使用定时器队列

Creates a timer-queue timer. This timer expires at the specified due time, then after every specified period. When the timer expires, the callback function is called.

创建一个timer-queue计时器。这个计时器在指定的到期时间过期,然后在每一个指定的时间段结束。当计时器过期时,将调用回调函数。

The following example creates a timer routine that will be executed by a thread from a timer queue after a 10 second delay. First, the code uses the CreateEvent function to create an event object that is signaled when the timer-queue thread completes. Then it creates a timer queue and a timer-queue timer, using the CreateTimerQueue and CreateTimerQueueTimer functions, respectively. The code uses the WaitForSingleObject function to determine when the timer routine has completed. Finally, the code calls DeleteTimerQueue to clean up.

下面的示例创建一个定时器例程,该例程将在10秒延迟后由一个线程从计时器队列执行。首先,代码使用CreateEvent函数创建一个事件对象,当timer-queue线程完成时,该事件对象将被释放。然后,分别使用CreateTimerQueue和CreateTimerQueueTimer函数创建一个计时器队列和一个计时器队列计时器。代码使用WaitForSingleObject函数来确定定时器例程何时完成。最后,代码调用DeleteTimerQueue来清理。

For more information on the timer routine, see WaitOrTimerCallback.

有关计时器例程的更多信息,请参见WaitOrTimerCallback。

Example code from MSDN:

从MSDN示例代码:

#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;
}

This is another example code from MSDN

这是MSDN的另一个示例代码。

This is another example from Codeproject

这是Codeproject的另一个例子。

#include <windows.h>
HANDLE hTimer = NULL;
unsigned long _stdcall Timer(void*)
{
    int nCount = 0;
    while(nCount < 10)
    {
    WaitForSingleObject(hTimer, 5000);
    cout << "5 s\n";
    nCount++;
    }
    cout << "50 secs\n";
    return 0;
}
void main()
{
    DWORD tid;
    hTimer = CreateEvent(NULL, FALSE, FALSE, NULL);
    CreateThread(NULL, 0, Timer, NULL, 0, &tid);
    int t;
    while(cin >> t)
    {
        if(0==t)
            SetEvent(hTimer);
    }
    CloseHandle(hTimer);
}

Resource:

资源:

#6


0  

Very simple timer without Windows

非常简单的没有窗户的计时器。

MSG Msg;

UINT TimerId = (UINT)SetTimer(NULL, 0, 0, NULL); // 0 minute

while (TRUE)
{
    GetMessage(&Msg, NULL, 0, 0);

    if (Msg.message == WM_TIMER)
    {
        KillTimer(NULL, TimerId);

        cout << "timer message\n";

        TimerId = (UINT)SetTimer(NULL, 0, 60000, NULL); // one minute.
    }

    DispatchMessage(&Msg);
}

#1


9  

You can use CreateTimerQueueTimer function

您可以使用CreateTimerQueueTimer函数。

HANDLE timer_handle_;
CreateTimerQueueTimer(&timer_handle_, NULL, TimerProc, user_object_ptr, 10, 0, WT_EXECUTEDEFAULT);
//callback
void TimerProc(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
{
    user_object* mgr = (user_object*) lpParameter;
    mgr->do();
    DeleteTimerQueueTimer(NULL, timer_handle_, NULL);
    timer_handle_ = NULL;
}

#2


5  

Timers set using the SetTimer API require a Windows message processing function to be actively running, as that is where the time messages are sent.

使用SetTimer API设置的计时器需要一个Windows消息处理函数来运行,因为这是发送时间消息的地方。

If you need a timer thread then you could register a Window class and create a default window message pump (See this article for a short example), but a simpler process would probably be to just spin up a second thread to handle your timing events and send notifications.

如果您需要一个计时器线程,那么您可以注册一个窗口类并创建一个默认的窗口消息源(请参阅本文的一个简短示例),但是一个更简单的过程可能是仅仅创建第二个线程来处理您的计时事件并发送通知。

#3


4  

Have a look at the following example which shows how to use WM_TIMER messages with a console app:

下面的示例展示了如何使用一个控制台应用程序使用WM_TIMER消息:

(Credit to the simplesamples.info site)

(归功于simplesamples.info网站)

#define STRICT 1 
#include <windows.h>
#include <iostream.h>

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) {
  cout << "Time: " << dwTime << '\n';
  cout.flush();
}

int main(int argc, char *argv[], char *envp[]) {
      int Counter=0;
      MSG Msg;
      UINT TimerId = SetTimer(NULL, 0, 500, &TimerProc);

      cout << "TimerId: " << TimerId << '\n';
      if (!TimerId)
        return 16;
      while (GetMessage(&Msg, NULL, 0, 0)) {
        ++Counter;
      if (Msg.message == WM_TIMER)
        cout << "Counter: " << Counter << "; timer message\n";
      else
        cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
      DispatchMessage(&Msg);
    }

    KillTimer(NULL, TimerId);

    return 0;
}

#4


1  

Have you considered Waitable Timers or Timer Queues? While it is possible to use SetTimer from a console app, these other facilities might be more appropriate for you.

您是否考虑过Waitable计时器或计时器队列?虽然可以从控制台应用程序使用SetTimer,但是这些其他的工具可能更适合您。

#5


1  

Using Timer Queues

使用定时器队列

Creates a timer-queue timer. This timer expires at the specified due time, then after every specified period. When the timer expires, the callback function is called.

创建一个timer-queue计时器。这个计时器在指定的到期时间过期,然后在每一个指定的时间段结束。当计时器过期时,将调用回调函数。

The following example creates a timer routine that will be executed by a thread from a timer queue after a 10 second delay. First, the code uses the CreateEvent function to create an event object that is signaled when the timer-queue thread completes. Then it creates a timer queue and a timer-queue timer, using the CreateTimerQueue and CreateTimerQueueTimer functions, respectively. The code uses the WaitForSingleObject function to determine when the timer routine has completed. Finally, the code calls DeleteTimerQueue to clean up.

下面的示例创建一个定时器例程,该例程将在10秒延迟后由一个线程从计时器队列执行。首先,代码使用CreateEvent函数创建一个事件对象,当timer-queue线程完成时,该事件对象将被释放。然后,分别使用CreateTimerQueue和CreateTimerQueueTimer函数创建一个计时器队列和一个计时器队列计时器。代码使用WaitForSingleObject函数来确定定时器例程何时完成。最后,代码调用DeleteTimerQueue来清理。

For more information on the timer routine, see WaitOrTimerCallback.

有关计时器例程的更多信息,请参见WaitOrTimerCallback。

Example code from MSDN:

从MSDN示例代码:

#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;
}

This is another example code from MSDN

这是MSDN的另一个示例代码。

This is another example from Codeproject

这是Codeproject的另一个例子。

#include <windows.h>
HANDLE hTimer = NULL;
unsigned long _stdcall Timer(void*)
{
    int nCount = 0;
    while(nCount < 10)
    {
    WaitForSingleObject(hTimer, 5000);
    cout << "5 s\n";
    nCount++;
    }
    cout << "50 secs\n";
    return 0;
}
void main()
{
    DWORD tid;
    hTimer = CreateEvent(NULL, FALSE, FALSE, NULL);
    CreateThread(NULL, 0, Timer, NULL, 0, &tid);
    int t;
    while(cin >> t)
    {
        if(0==t)
            SetEvent(hTimer);
    }
    CloseHandle(hTimer);
}

Resource:

资源:

#6


0  

Very simple timer without Windows

非常简单的没有窗户的计时器。

MSG Msg;

UINT TimerId = (UINT)SetTimer(NULL, 0, 0, NULL); // 0 minute

while (TRUE)
{
    GetMessage(&Msg, NULL, 0, 0);

    if (Msg.message == WM_TIMER)
    {
        KillTimer(NULL, TimerId);

        cout << "timer message\n";

        TimerId = (UINT)SetTimer(NULL, 0, 60000, NULL); // one minute.
    }

    DispatchMessage(&Msg);
}