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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7531650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:04:48  来源:igfitidea点击:

Can I use a SetTimer() API in a console C++ application?

c++windowstimerconsole

提问by JallenA1

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?

是否有解决方法可以使这项工作?

回答by Marx Yu

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

回答by Chad

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

使用SetTimerAPI设置的计时器需要主动运行 Windows 消息处理函数,因为这是发送时间消息的地方。

If you need a timer thread then you could register a Window class and create a default window message pump (See this articlefor 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.

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

回答by Michael Goldshteyn

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.infosite)

归功于 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;
}

回答by Aaron Klotz

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

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

回答by Elshan

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.

The following example creates a timer routine that will be executed by a thread from a timer queueafter a 10 second delay. First, the code uses the CreateEventfunction 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 CreateTimerQueueand CreateTimerQueueTimer functions, respectively. The code uses the WaitForSingleObjectfunction to determine when the timer routine has completed. Finally, the code calls DeleteTimerQueueto clean up.

使用定时器队列

创建一个计时器队列计时器。此计时器在指定的到期时间到期,然后在每个指定的时间段后到期。当定时器到期时,回调函数被调用。

下面的示例创建一个计时器例程,该例程将由计时器队列中的线程在 10 秒延迟后执行。首先,代码使用该CreateEvent函数创建一个事件对象,该对象在计时器队列线程完成时发出信号。然后,它CreateTimerQueue分别使用CreateTimerQueueTimer 和 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:

资源:

回答by Alan10977

Very simple timer without Windows

没有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);
}