Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Вниз

Не срабатывает SetWaitableTimer.   Найти похожие ветки 

 
Б   (2010-04-15 12:18) [0]

Здрасти!

Почему не срабатывает 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-15 12:31) [1]

> Б  (15.04.2010 12:18:00)  [0]

Где обработка ошибки, а не это позорное "MessageBox(0, "No create timer!","


 
Б   (2010-04-15 12:35) [2]

А какая тут разница?
RaiseLastOSError или MessageBox.


 
Leonid Troyanovsky ©   (2010-04-15 12:47) [3]


> Б   (15.04.10 12:18)  

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

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

--
Regards, LVT.


 
Б   (2010-04-15 13:00) [4]


> Leonid Troyanovsky ©   (15.04.10 12:47) [3]

Спасибо за пример.

Только я не понял, почему мой пример не работает без SleepEx.
С ним приложение зависает.
Как этого избежать?


 
Anatoly Podgoretsky ©   (2010-04-15 13:13) [5]

> Б  (15.04.2010 12:35:02)  [2]

За RaiseLastOSError тебе сисадмины будут ноги целовать, а за твое самоувереное морду бить.


 
Leonid Troyanovsky ©   (2010-04-15 13:14) [6]


> Б   (15.04.10 13:00) [4]

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

http://msdn.microsoft.com/en-us/library/ms686898(VS.85).aspx

--
Regards, LVT.


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


> Б   (15.04.10 13:00) [4]


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

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


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


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


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


> 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 16:45) [9]


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


Гы


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

> Гы

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


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

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


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

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

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


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

Кури MsgWaitForMultipleObjectsEx()


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

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

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



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;



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


> Б   (15.04.10 18:56) [14]

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

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

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

--
Regards, LVT.


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

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


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

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


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


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


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


 
Leonid Troyanovsky ©   (2010-04-15 21:42) [19]


> Б   (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-16 09:40) [20]


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


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


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


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


 
Leonid Troyanovsky ©   (2010-04-16 10:18) [22]


> Б   (16.04.10 09:40) [20]

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

--
Regards, LVT.


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


> Сергей М. ©   (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.


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

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


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

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

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

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


 
Anatoly Podgoretsky ©   (2010-04-16 18:56) [26]

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

GetTime убери


 
Б   (2010-04-16 22:44) [27]

Забыл, что Now возвращает текущую дату и время, а не одну дату.

Почему не работает?:


// DateTimePicker"ы - настраиваются пользователем.
// У DateTimePicker2.Kind = dtkTime.
WakeUp.RunTimer(DateTimePicker1.Date + DateTimePicker2.Time);


 
Игорь Шевченко ©   (2010-04-16 23:00) [28]


> Почему не работает?:


не хочет


 
Б   (2010-04-16 23:09) [29]


> Игорь Шевченко ©   (16.04.10 23:00) [28]


Неожиданный ответ для вас. ;D

Вот так конвектирую время:


Var
 TimeFile: Int64;
 TimeSys : TSystemTime;
begin  
  DateTimeToSystemTime(WakeUpTime, TimeSys);
  Win32Check(SystemTimeToFileTime(TimeSys, TFILETIME(TimeFile)));



 
Leonid Troyanovsky ©   (2010-04-17 10:40) [30]


> Б   (16.04.10 11:08) [23]

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

Для гуевого приложения лучше вернуться к SetTimer.

--
Regards, LVT.


 
Б   (2010-04-17 13:05) [31]


> Leonid Troyanovsky ©   (17.04.10 10:40) [30]


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

В Caption выдаётся установленная дата и время.
Но будильник не срабатывает. В чём дело?


DateTimePicker1.Time:= DateTimePicker2.Time;

Caption:= DateTimeToStr(DateTimePicker1.Date);
WakeUp.RunTimer(DateTimePicker1.Date);


 
Б   (2010-04-17 21:34) [32]

Удалено модератором


 
Б   (2010-04-20 12:21) [33]

Остался последний вопрос:
Как прервать вызов MsgWaitForMultipleObjectsEx?


 
Leonid Troyanovsky ©   (2010-04-20 13:10) [34]


> Б   (20.04.10 12:21) [33]

> Как прервать вызов MsgWaitForMultipleObjectsEx?

PostMessage, QueueUserAPC.

--
Regards, LVT.


 
Сергей М. ©   (2010-04-20 13:10) [35]

Из другого потока уничтожить объект синхронизации или послать ожидающему потоку любое сообщение, например, WM_NULL


 
Вариант   (2010-04-20 13:37) [36]


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


> Из другого потока уничтожить объект синхронизации

Не факт. Я бы не стал на это рассчитывать.  Поведение функции ожидания события (Msg)WaitForXXX  при CloseHandle (если это имелось ввиду под уничтожением) может быть не определенным в общем случае.


 
Leonid Troyanovsky ©   (2010-04-20 13:56) [37]


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

> ожидающему потоку любое сообщение

Про "послать потоку" ИШ ссылался недавно:
http://transl-gunsmoker.blogspot.com/2010/04/blog-post_05.html

Ну, а про уничтожение
http://msdn.microsoft.com/en-us/library/ms687069(VS.85).aspx ;)

--
Regards, LVT.


 
Б   (2010-04-20 14:01) [38]

Начал делать через PostMessage.


Const
 WM_WAIT_STOP = WM_NULL + 1;

. . . . .

WAIT_OBJECT_0 + 1:                           // Process messages.
           begin
             If PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
             Case Msg.Message of
                WM_QUIT:                                // Press close [x].
                begin
                  PostQuitMessage(0);
                  Exit;
                end;
                WM_WAIT_STOP: Exit;
                else begin
                  TranslateMessage(Msg);
                  DispatchMessage(Msg);
                end
             end;
           end;

. . . . .

procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
 If WakeUp.RunTimer(DateTimePicker1.Time, OpenDialog1.FileName) then
 begin
    MessageBox(0, PCHAR(" Дождались! ;)"), "!", MB_OK or MB_ICONINFORMATION)
   // RaiseLastOSError;

 end;

procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
  PostMessage(Handle, WM_WAIT_STOP, 0, 0);
end;



При нажатии SpeedButton3, будильник не вызывается,
но и не показывается MessageBox, говорящий о завершении ожидания.
Почему?


 
Б   (2010-04-20 14:02) [39]

Поправка: Не WM_WAIT_STOP, а WM_NULL.


 
Б   (2010-04-20 14:12) [40]

Решил.
Надо было при ловле WM_NULL возвращать ещё и Result = True.



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.055 c
6-1218124422
dozcent
2008-08-07 19:53
2010.08.27
TSeverThead, TServerSocket


15-1266047756
oldman
2010-02-13 10:55
2010.08.27
Ну вот и началась Олимпиада!


2-1265804991
Вася
2010-02-10 15:29
2010.08.27
A.V. при закрытии формы с TWebBrowser


2-1267610535
@!!ex
2010-03-03 13:02
2010.08.27
Как в синхронном режиме получить ответ от TCP сервера?


15-1273756585
oldman
2010-05-13 17:16
2010.08.27
Визитная карточка Samsung - оружие самурая...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский