Конференция "WinAPI" » почему не срабатывает таймер? [D7, WinXP]
 
  • Dmitry_177 (29.10.07 13:44) [0]
    Есть ini-файл, из него считывается время срабатывания таймеров(их несколько) но почему то не срабатывает таймер.. Приведу весь кусок кода:


    program TimeServ;

    uses
     Windows,
     Messages,
     Classes,
     IniFiles,
     SysUtils;

    var
     AMessage: TMsg;
     hTimers: array of THandle;

    procedure TimerAPCProc(lpArgToCompletionRoutine: PChar; dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;
    begin
     MessageBox(0, '1', '1', 0);  // не срабатывает почему то..
    end;

    function InstallTimers: BOOL;
    var
     Sections: TStrings;
     iTimer: integer;
     sysTime: SYSTEMTIME;
     fTime: FILETIME;
    begin
       try
         Sections := TStringList.Create;

         with TIniFile.Create('TimeManager.ini') do
           try
             ReadSections(Sections);
             if Sections.Count > 0 then
               begin
                 SetLength(hTimers, Sections.Count);
                 for iTimer := 0 to Sections.Count - 1 do
                   begin
                     hTimers[iTimer] := CreateWaitableTimer(nil, false, nil);
                     DateTimeToSystemTime(StrToDateTime(Sections[iTimer]), sysTime);  // запись происходит функцией DateTimeToStr, в переменной sysTime смотрел дата с временем правильно считывается..
                     SystemTimeToFileTime(sysTime, fTime);
                     LocalFileTimeToFileTime(fTime, fTime);
                     SetWaitableTimer(hTimers[iTimer], TLargeInteger(fTime), 0, @TimerAPCProc, nil, false);
                   end;
               end;
           finally
             Free;
           end;

       finally
         Sections.Free;
       end;
    end;

    function UninstallTimers: BOOL;
    var
     iTimer: integer;
    begin
     for iTimer := 0 to Length(hTimers) - 1 do
       begin
         CancelWaitableTimer(hTimers[iTimer]);
         CloseHandle(hTimers[iTimer]);
       end;
     SetLength(hTimers, 0);
    end;

    begin
     InstallTimers;

     while GetMessage(AMessage, 0, 0, 0) do
       DispatchMessage(AMessage);

     UninstallTimers;
    end.



    Подскажите пожалуйста..
  • Сергей М. © (29.10.07 13:54) [1]
    SetWaitableTimer - это функция.
  • Dmitry_177 (29.10.07 14:09) [2]
    она возвращает true, т.е. все успешно..
  • Leonid Troyanovsky © (29.10.07 14:10) [3]

    > Dmitry_177   (29.10.07 13:44)  

    >  while GetMessage(AMessage, 0, 0, 0) do
    >    DispatchMessage(AMessage);

    Это ж не user timer, попробуй, скажем, SleepEx(INFINITE, True).

    --
    Regards, LVT.
  • Сергей М. © (29.10.07 14:19) [4]

    > Dmitry_177   (29.10.07 14:09) [2]


    If you call SetWaitableTimer and the thread is not in an alertable state, the completion routine is canceled.

    Нить находится в тревожном состоянии (alertable state) только в момент исполнения ф-ции   WaitForSingleObjectEx, [Msg]WaitForMultipleObjectsEx, Read/WriteFileEx, SleepEx.
  • Dmitry_177 (29.10.07 14:27) [5]
    т.е. вот так чтоли? =)

    begin
     InstallTimers;

     SleepEx(INFINITE, True);

     UninstallTimers;
    end.

  • Сергей М. © (29.10.07 14:28) [6]
    Ну хотя бы так.
  • Dmitry_177 (29.10.07 14:38) [7]
    эм.. сработало :) но только вот программа после срабатывания выключилась почему то.. что-то непойму почему, ведь бесконечное же ожидание..
  • Сергей М. © (29.10.07 14:40) [8]
    А справку читать - дело не царское ?
    Там же логика работы этой (и других упомянутых) ф-ции описана довольно четко.
  • Dmitry_177 (29.10.07 18:08) [9]
    Прочитал повнимательней.. понял в чем дело.. а вот как сделать так чтобы все таймеры сработали? Что-то я не придумаю никак.. Может SleepEx в бесконечный цикл поставить? Ведь программа вылетает при первом же срабатывании..
  • Leonid Troyanovsky © (29.10.07 19:42) [10]

    > Dmitry_177   (29.10.07 18:08) [9]

    > Прочитал повнимательней.. понял в чем дело.. а вот как сделать
    > так чтобы все таймеры сработали?

    Если таймеров не более 64, то все можно отслеживать
    в одном потоке путем WaitForMultipleObjects|Ex.

    Ну, а если более, то в нескольких потоках.

    --
    Regards, LVT.
  • Dmitry_177 (29.10.07 19:48) [11]
    само время срабатывания таймеров может быть записано в файле совсем не по порядку(т.е. не по возрастанию).. а если будет так что более позднее срабатывание считается первее чем более раннее?
  • Leonid Troyanovsky © (29.10.07 21:47) [12]

    > Dmitry_177   (29.10.07 19:48) [11]

    А то.

    --
    Regards, LVT.
  • Dmitry_177 (29.10.07 22:30) [13]
    я сделал в цикле SleepEx, вроде все работает =) только у меня еще один вопрос возник.. Мне нужно в процедуру TimerAPCProc передать значение Sections[iTimer], т.е. дату с временем в строке, делаю так:


    SetWaitableTimer(hTimers[iTimer], TLargeInteger(fTime), 0, @TimerAPCProc, PChar(Sections[iTimer]), false);



    а в lpArgToCompletionRoutine обрезанная строка, т.е. например исходная такая: 29.10.2007 21:33:00 а в процедуре она такая: 29.10.2007 21:33
  • Германн © (30.10.07 01:35) [14]

    > а в lpArgToCompletionRoutine обрезанная строка, т.е. например
    > исходная такая: 29.10.2007 21:33:00 а в процедуре она такая:
    >  29.10.2007 21:33
    >

    "Гложат меня смутные сомнения. У Шпака - магнитофон, у посла - медальон"?
    Очень смущают "конечные нули", на которых строка обрезается. Возможно я и не прав. Но...
  • Сергей М. © (30.10.07 08:15) [15]

    > Dmitry_177   (29.10.07 22:30) [13]


    Так делать нельзя вообще.

    Выражением

    PChar(Sections[iTimer])



    ты передал адрес строки, время жизни которой равно времени жизни объекта Sections, который уничтожается тобой сразу же по возврату из InstallTimers.
  • Dmitry_177 (30.10.07 13:34) [16]
    да уж.. а как тогда? Может так тогда?

    var
    str: string;

    function InstallTimers: BOOL;
    begin
    ...

    str := PChar(Sections[iTimer]);
    SetWaitableTimer(hTimers[iTimer], TLargeInteger(fTime), 0, @TimerAPCProc, PChar(str), false);

    ...
    end;

  • Dmitry_177 (30.10.07 13:51) [17]
    блин, торможу сорри.. сделал Sections глобальной переменной и все ок
  • Dmitry_177 (30.10.07 14:29) [18]
    Еще маленький вопросик, можно ли в TimerAPCProc определить какой таймер сработал? Ведь если таймер с периодом он так и будет дергать TimerAPCProc, так вот если уже больше он не понадобится, чтоб можно его было хлопнуть в этой же TimerAPCProc..
  • Сергей М. © (30.10.07 14:56) [19]

    > можно ли в TimerAPCProc определить какой таймер сработал?


    На то у TimerAPCProc и существует 1-й параметр - передавай через него хоть хэндл, хоть черта лысого)
 
Конференция "WinAPI" » почему не срабатывает таймер? [D7, WinXP]
Есть новые Нет новых   [120365   +49][b:0][p:0.003]