简体   繁体   English

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

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

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. 我有一个控制台应用程序,它使用一个DLL文件,该文件使用SetTimer()调用来创建一个计时器并在其自身内部激活一个函数。 The call is below: 电话如下:

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). 我假设因为我的是一个控制台应用程序而不是标准的Windows GUI应用程序(就像最初使用DLL文件的地方一样)。 This stops a key part of the DLL files functionality from working. 这将阻止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? 是否有工作要做到这一点?

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

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

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

Have you considered Waitable Timers or Timer Queues ? 你考虑过Waitable TimersTimer Queues吗? While it is possible to use SetTimer from a console app, these other facilities might be more appropriate for you. 虽然可以从控制台应用程序使用SetTimer ,但这些其他设施可能更适合您。

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 queue after a 10 second delay. 以下示例创建一个计时器例程,该例程将在10秒延迟后由来自计时器队列的线程执行。 First, the code uses the CreateEvent function to create an event object that is signaled when the timer-queue thread completes. 首先,代码使用CreateEvent函数创建一个事件对象,该事件对象在计时器队列线程完成时发出信号。 Then it creates a timer queue and a timer-queue timer, using the CreateTimerQueue and CreateTimerQueueTimer functions, respectively. 然后,它分别使用CreateTimerQueue和CreateTimerQueueTimer函数创建计时器队列和计时器队列计时器。 The code uses the WaitForSingleObject function to determine when the timer routine has completed. 代码使用WaitForSingleObject函数来确定计时器例程何时完成。 Finally, the code calls DeleteTimerQueue to clean up. 最后,代码调用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: 资源:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM