Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Не срабатывает SetWaitableTimer. [D7, XP]


Страницы:   1 2 3

Б ©   (2010-04-15 12:18:00) 

Здрасти!

Почему не срабатывает SetWaitableTimer?
Будильник должен включиться ровно через 1 минуту после запуска.


Var
 HTIMER  : LongWord;
 TimeSys : TSystemTime;
 TimeFile: TFileTime;

Procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue, dwTimerHighValue: DWORD); stdcall;
begin
 MessageBox(0, 'Wake Up!', '!', MB_OK or MB_ICONERROR);
End;

Procedure XRunTimer(Hour, Minute: word);
begin
 HTIMER:= CreateWaitableTimer(nil, False, nil);
 If (HTIMER = 0) then
 begin
   MessageBox(0, 'No create timer!', '!', MB_OK or MB_ICONERROR);
   Exit;
 end;

 GetLocalTime(TimeSys);                 // Текущая дата и время.
 TimeSys.wMinute:= TimeSys.wMinute + 1; // Должен сработать через 1 минуту.
 (*
 With TimeSys do
 begin
   wHour  := Hour;
   wMinute:= Minute;
 end;
 *)

 Win32Check(SystemTimeToFileTime(TimeSys, TimeFile));
 Win32Check(SetWaitableTimer(HTIMER, INT64(TimeFile), 0, @TimerAPCProc, nil, False));
End;

procedure TForm1.FormCreate(Sender: TObject);
begin
 XRunTimer(StrToInt(Edit1.Text), StrToInt(Edit2.Text));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 CloseHandle(HTIMER);
end;


Anatoly Podgoretsky   (2010-04-16 18:56:00) [21]

> Б  (16.04.2010 17:48:25)  [25]

GetTime убери


Б   (2010-04-16 17:48:00) [22]

Остался 1 вопрос.

На вход функции запуска будильника принимается одна переменная типа TDateTime.
Как правильно передать ей дату и время?

WakeUp.RunTimer(Now + GetTime);  // Для примера текущая дата и время.


Б   (2010-04-16 11:23:00) [23]

Тем более, с MsgWaitForMultipleObjectsEx
можно сделать поддержку нескольких таймеров и сделать
подобие планировщика задач.


Б   (2010-04-16 11:08:00) [24]


> Сергей М. ©   (16.04.10 10:13) [21]


Если указать не INFINITE, а к примеру 10, то функция по идее должна
возвратить управление, выйти в начало Repeat, где произойдёт обработка мессаг окна
и попробовать снова.
Но происходит RaiseLastOSError.

> Leonid Troyanovsky ©   (16.04.10 10:18) [22]

Не, лучше вернуть к прежнему способу с APC-proc.

Почитал тут: http://www.compress.ru/Archive/CP/2001/9/38/index.htm
, чтобы GUI реагировал на нажатия и окно перерисовывалось нужно использовать как ни крути MsgWaitForMultipleObjectsEx.


Leonid Troyanovsky   (2010-04-16 10:18:00) [25]


> Б   (16.04.10 09:40) [20]

http://rsdn.ru/forum/delphi/500558.1.aspx

--
Regards, LVT.


Сергей М.   (2010-04-16 10:13:00) [26]


> программа виснет


Конечно она виснет)
Ты же заставил ее "висеть" вызвав ф-цию ожидания, не реагирующую на оконные сообщения)


Б   (2010-04-16 09:40:00) [27]


> Leonid Troyanovsky ©   (15.04.10 21:42) [19]


Да, лучше использовать WaitForSingleObject, т.к. объект ожидания 1.
Переделал так, но всё программа виснет:


If SetWaitableTimer(HTIMER, TimeFile, 0, nil, nil, True) then
   begin
     If (GetLastError = ERROR_NOT_SUPPORTED) then
     begin
       MessageBox(0, 'Resume - no supported!', '!', MB_OK or MB_ICONERROR);

     end;
 
    Repeat
      Application.ProcessMessages;
      If Application.Terminated then Break;

      If (WaitForSingleObject(HTIMER, INFINITE) = WAIT_OBJECT_0) then
      begin
        Audio.Play(WakeUp.FAudID);
        MessageBox(0, PCHAR('Wake Up! - ' + TimeToStr(Time)), '!', MB_OK or MB_ICONINFORMATION);
        Break;
      end else
      begin
        RaiseLastOSError;
        Break;
      end;
    Until False;


Leonid Troyanovsky   (2010-04-15 21:42:00) [28]


> Б   (15.04.10 20:49) [18]

> Тогда где ставить обработчик срабатывания будильника?

http://msdn.microsoft.com/en-us/library/ms687008

> Программа не хочет закрываться крестиком.

[15]

 Application.ProcessMessages;
 if Application.Terminated then
   Exit;

--
Regards, LVT.


Б   (2010-04-15 20:49:00) [29]


> Кста, для WaitableTimer TimerAPCProc не обязательна.


Тогда где ставить обработчик срабатывания будильника?


Б   (2010-04-15 19:56:00) [30]

Программа не хочет закрываться крестиком.


Б   (2010-04-15 19:38:00) [31]

Заменил QS_ALLPOSTMESSAGE на QS_ALLINPUT и всё заработало наконец-то. ;)


Leonid Troyanovsky   (2010-04-15 19:20:00) [32]


> Б   (15.04.10 18:56) [14]

> Как правильно её вызывать?

http://rsdn.ru/forum/delphi/500558.1.aspx

Ex оставлено в качестве домашнего задания.
Кста, для WaitableTimer TimerAPCProc не обязательна.

--
Regards, LVT.


Б   (2010-04-15 18:56:00) [33]

Замутно всё как-то...
Вроде бы сделал, обработку мессаг от зависания.

Как правильно её вызывать?



If SetWaitableTimer(HTIMER, TimeFile, 0, @TimerAPCProc, nil, True) then
   begin
     If (GetLastError = ERROR_NOT_SUPPORTED) then
     begin
       MessageBox(0, 'Resume - no supported!', '!', MB_OK or MB_ICONERROR);

     end;

     Repeat
       Case MsgWaitForMultipleObjectsEx(1, HTIMER, INFINITE, QS_ALLPOSTMESSAGE, 0) of
         WAIT_OBJECT_0    : Break;                           // Finish.
         WAIT_OBJECT_0 + 1: Application.ProcessMessages;     // Process messages.
         else                                                // Error.
           RaiseLastOSError;
       end;
     Until False;

     SleepEx(INFINITE, True);
   end else
     RaiseLastOSError;


Сергей М.   (2010-04-15 17:55:00) [34]

Кури MsgWaitForMultipleObjectsEx()


Б   (2010-04-15 17:34:00) [35]

Как теперь избавиться от зависания?

Создание потока? Application.ProcessMessages?


Б   (2010-04-15 17:16:00) [36]

Ура!
Проверил, врубается из ждущего режима и проигрывает добавленную .mp3-ху. ;)


Б   (2010-04-15 16:50:00) [37]

> Гы

Или ждущий режим?
Или параметр fResume не для того?


Игорь Шевченко   (2010-04-15 16:45:00) [38]


> которая могла бы включаться даже из состояние спящего режима.


Гы


Б   (2010-04-15 16:19:00) [39]


> Anatoly Podgoretsky ©   (15.04.10 13:13) [5]
> > Б  (15.04.2010 12:35:02)  [2]
>
> За RaiseLastOSError тебе сисадмины будут ноги целовать,
> а за твое самоувереное морду бить.


Пока обойдусь без фетишистов.

> Вариант   (15.04.10 13:15) [7]
> Используй обычный таймер в главном потоке - это тебе будет проще, чем другие варианты, которые конечно тоже существуют.

Цель всего этого дела, создать программу на подобии будильника,
которая могла бы включаться даже из состояние спящего режима.

> Leonid Troyanovsky ©   (15.04.10 13:14) [6]  

Поток виснет от этого.


Вариант   (2010-04-15 13:15:00) [40]


> Б   (15.04.10 13:00) [4]


> Только я не понял, почему мой пример не работает без SleepEx

Потому, что TimerAPCProc - это APCProc.


> С ним приложение зависает.
> Как этого избежать?


Используй обычный таймер в главном потоке - это тебе будет проще, чем другие варианты, которые конечно тоже существуют.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо