Могу ли я использовать SetTimer () API в консольном приложении C ++? - PullRequest
8 голосов
/ 23 сентября 2011

У меня есть консольное приложение, которое использует файл DLL, который использует вызов SetTimer() для создания таймера и запуска функции внутри себя.Вызов ниже:

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

Ожидается получение сообщений таймера, но этого никогда не происходит.Я предполагаю, потому что у меня консольное приложение, а не стандартное приложение с графическим интерфейсом Windows (например, где изначально использовался файл DLL).Это останавливает работу ключевой части функциональности DLL-файлов.

Моему приложению необходимо оставаться консольным приложением, и я не могу изменить DLL.

Ответы [ 6 ]

9 голосов
/ 24 сентября 2012

Вы можете использовать Функция 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;
}
5 голосов
/ 23 сентября 2011

Таймеры, установленные с помощью API SetTimer, требуют, чтобы функция обработки сообщений Windows была активно запущена, поскольку именно здесь отправляются сообщения времени.

Если вам нужен поток таймера, то вы можете зарегистрировать класс Window и создать насос сообщений окна по умолчанию (см. эту статью для краткого примера), но более простой процесс, вероятно, заключался бы в простом ускорении. второй поток для обработки ваших временных событий и отправки уведомлений.

4 голосов
/ 23 сентября 2011

Посмотрите на следующий пример, который показывает, как использовать сообщения WM_TIMER с консольным приложением:

(Кредит на сайт 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;
}
2 голосов
/ 23 сентября 2011

Рассматривали ли вы Таймеры ожидания или Очереди таймеров ? Хотя можно использовать SetTimer из консольного приложения, эти другие средства могут быть более подходящими для вас.

1 голос
/ 14 июля 2016

Использование очередей таймера

Создает таймер очереди таймера. Этот таймер истекает в указанный срок время, то после каждого указанного периода. Когда таймер истекает, вызывается функция обратного вызова.

В следующем примере создается процедура таймера, которая будет выполняться поток из очереди таймера после 10-секундной задержки. Во-первых, код использует функцию CreateEvent для создания объекта события это сигнализируется, когда поток очереди таймера завершается. Затем это создает очередь таймера и таймер очереди таймера, используя CreateTimerQueue и функции CreateTimerQueueTimer, соответственно. Код использует функцию WaitForSingleObject для определить, когда процедура таймера завершена. Наконец, код звонит DeleteTimerQueue на уборку.

Для получения дополнительной информации о процедуре таймера см. WaitOrTimerCallback.

Пример кода из 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;
}

Это еще один пример кода из MSDN

Это еще один пример из 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);
}

Ресурс:

0 голосов
/ 03 июня 2015

Очень простой таймер без 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);
}
...