Аналог SetTimer() без привязки к окну

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

Есть задача - вызвать ф-цию приблизительно через энцать милисекунд.

Я сейчас это делаю так:
1. Устанавливаю таймер с помощью ::SetTimer(), беря хенд любого окна из моего проекта.
2. В ф-ции обработчике таймера я вызываю нужную мне ф-цию.
Недостаток - привязываюсь к окну, а это меня неустраивает (я пишу независимый модуль, который не имеет никакого отношения к окнам).

Второй вариант, что мне приходит в голову:
1. Создать отдельную очередь.
2. И в этой очереди через некоторое время вызвать нужную мне ф-цию.
Недостаток - я считаю, что это слишком дорогостоящие затраты системных ресурсов.

Был бы рад выслушать прочие идеи по данному вопросу.
Оптимальный, как мне кажется, вариант - вызвать некую WinAPI'шную ф-цию, где в качестве параметров передаются моя callback ф-ция, и время через которое вызовется эта ф-ция. Т.е. почти полный аналог ::SetTimer(), но без привязки к окнам...
Серёга, любит баранью ногу.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Если повнимательнее почитать про параметры функции ::SetTimer(), то можно увидеть что там есть четвертый параметр с указателем на функцию, которая должна быть вызвана после истечения интервала. Кроме того, чтобы не привязываться к окну (и не посылать никуда собщений), можно передать NULL вместо хендла окна
Кроме того, есть функции CreateWaitableTimer() для многопоточной среды или QueryPerformanceCounter() для спец. задач.
2B OR NOT(2B) = FF
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

Мне такое неподходит:
MSDN
If hWnd parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
У меня callback ф-ция - static мембер моего класса. Т.е. вызов

Код: Выделить всё

HWND hWnd = NULL; // ::GetForegroundWindow();
::SetTimer(
  hWnd,
  (UINT)this,
  0,
  CMyClass::TimerProc);
приводит к тому что пришедший параметр (идентификатор таймера) в ф-цию CMyClass::TimerProc недействителен... :(

Код: Выделить всё

VOID CALLBACK CMyClass::TimerProc(
   HWND hwnd,    // handle of window for timer messages
   UINT uMsg,    // WM_TIMER message
   UINT idEvent, // timer identifier
   DWORD dwTime  // current system time
)
{
   CMyClass *This = (CMyClass*)idEvent;
   if (This != NULL) {
      ::KillTimer(hwnd, idEvent);
      //This->...;
   }
}
Серёга, любит баранью ногу.
Hawk
Сообщения: 216
Зарегистрирован: 17 фев 2004, 14:52
Откуда: СПб
Контактная информация:

Ну сделай отдельный поток тогда
SeregaLBN
Сообщения: 23
Зарегистрирован: 17 фев 2004, 13:27
Откуда: Киев
Контактная информация:

Неа, всё гораздо проще.
Использую теперь multimedia timers (ф-ции timeGetDevCaps, timeBeginPeriod, timeSetEvent) или одну из ф-ций для работы с пулами потоков.
Т.е. теперь у меня реализовано так:

Код: Выделить всё

#if (_WIN32_WINNT >= 0x0500)
      // variant 1
      bRes = ::QueueUserWorkItem(CMyClass::AsyncFunc, (PVOID)this, 0);
#else
      // variant 2
      TIMECAPS tc;
      bRes = (TIMERR_NOERROR == ::timeGetDevCaps(&tc, sizeof(TIMECAPS)));
      if (bRes) {
         UINT uiTimerResolution = min(max(tc.wPeriodMin, 10), tc.wPeriodMax);
         ::timeBeginPeriod(uiTimerResolution);
         MMRESULT uTimerID = ::timeSetEvent(uiDelay, uiTimerResolution, CMyClass::MMTimerProc, (DWORD_PTR)this, TIME_ONESHOT);
         bRes = !!uTimerID;
      }
#endif
и соотв. callback ф-ции:

Код: Выделить всё

#if (_WIN32_WINNT >= 0x0500)
DWORD CALLBACK CMyClass::AsyncFunc(LPVOID lpThreadParameter) {
   CMyClass*This = (CMyClass*)lpThreadParameter;
   if (This != NULL) {
      //This->...
   }
   return 0;
}

#else

void CALLBACK CMyClass::MMTimerProc(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DWORD_PTR)
{
   CMyClass*This = (CMyClass*)dwUser;
   if (This != NULL) {
      //This->...
   }
   BOOL bRes = (TIMERR_NOERROR == ::timeKillEvent(uTimerID));
}
#endif
Серёга, любит баранью ногу.
Ответить