Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.08.03;
Скачать: CL | DM;

Вниз

почему не срабатывает таймер?   Найти похожие ветки 

 
Dmitry_177   (2007-10-29 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.


Подскажите пожалуйста..


 
Сергей М. ©   (2007-10-29 13:54) [1]

SetWaitableTimer - это функция.


 
Dmitry_177   (2007-10-29 14:09) [2]

она возвращает true, т.е. все успешно..


 
Leonid Troyanovsky ©   (2007-10-29 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.


 
Сергей М. ©   (2007-10-29 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   (2007-10-29 14:27) [5]

т.е. вот так чтоли? =)

begin
 InstallTimers;

 SleepEx(INFINITE, True);

 UninstallTimers;
end.


 
Сергей М. ©   (2007-10-29 14:28) [6]

Ну хотя бы так.


 
Dmitry_177   (2007-10-29 14:38) [7]

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


 
Сергей М. ©   (2007-10-29 14:40) [8]

А справку читать - дело не царское ?
Там же логика работы этой (и других упомянутых) ф-ции описана довольно четко.


 
Dmitry_177   (2007-10-29 18:08) [9]

Прочитал повнимательней.. понял в чем дело.. а вот как сделать так чтобы все таймеры сработали? Что-то я не придумаю никак.. Может SleepEx в бесконечный цикл поставить? Ведь программа вылетает при первом же срабатывании..


 
Leonid Troyanovsky ©   (2007-10-29 19:42) [10]


> Dmitry_177   (29.10.07 18:08) [9]

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

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

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

--
Regards, LVT.


 
Dmitry_177   (2007-10-29 19:48) [11]

само время срабатывания таймеров может быть записано в файле совсем не по порядку(т.е. не по возрастанию).. а если будет так что более позднее срабатывание считается первее чем более раннее?


 
Leonid Troyanovsky ©   (2007-10-29 21:47) [12]


> Dmitry_177   (29.10.07 19:48) [11]

А то.

--
Regards, LVT.


 
Dmitry_177   (2007-10-29 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


 
Германн ©   (2007-10-30 01:35) [14]


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

"Гложат меня смутные сомнения. У Шпака - магнитофон, у посла - медальон"?
Очень смущают "конечные нули", на которых строка обрезается. Возможно я и не прав. Но...


 
Сергей М. ©   (2007-10-30 08:15) [15]


> Dmitry_177   (29.10.07 22:30) [13]


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

Выражением

PChar(Sections[iTimer])

ты передал адрес строки, время жизни которой равно времени жизни объекта Sections, который уничтожается тобой сразу же по возврату из InstallTimers.


 
Dmitry_177   (2007-10-30 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   (2007-10-30 13:51) [17]

блин, торможу сорри.. сделал Sections глобальной переменной и все ок


 
Dmitry_177   (2007-10-30 14:29) [18]

Еще маленький вопросик, можно ли в TimerAPCProc определить какой таймер сработал? Ведь если таймер с периодом он так и будет дергать TimerAPCProc, так вот если уже больше он не понадобится, чтоб можно его было хлопнуть в этой же TimerAPCProc..


 
Сергей М. ©   (2007-10-30 14:56) [19]


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


На то у TimerAPCProc и существует 1-й параметр - передавай через него хоть хэндл, хоть черта лысого)


 
Dmitry_177   (2007-10-30 14:59) [20]

мне нужно еще и строку передавать..


 
Сергей М. ©   (2007-10-30 15:06) [21]


> мне нужно еще и строку передавать


А про record"ы ты что-нить слышал ?)


 
Dmitry_177   (2007-10-30 15:12) [22]

свою структуру? в принципе да.. т.е. если сделать как-нибудь так:

type
 TDataTimer = packed record
   hTimer: THandle;
   Str: PChar;
 end;


то придется еще и массив этих структур создавать?


 
Dmitry_177   (2007-10-30 15:41) [23]

function InstallTimers: BOOL;
var
 DataTimer: TDataTimer;
begin
...

 DataTimer.hTimer := hTimers[iTimer];
 DataTimer.StrDateTime := PChar(Sections[iTimer]);
 SetWaitableTimer(hTimers[iTimer], TLargeInteger(fTime), 60000, @TimerAPCProc, Pointer(DataTimer), false);

...
end;


Вот так ошибка: Invalid typecast


 
Сергей М. ©   (2007-10-30 15:51) [24]


> придется еще и массив этих структур создавать?
>


Нафига ?


> Вот так ошибка: Invalid typecast


Почему бы и нет, если ты тип, несовместимый с указательным, пытаешься привести к указательному ?


 
Dmitry_177   (2007-10-30 15:52) [25]


> Нафига ?

а что тогда можно сделать?


 
Сергей М. ©   (2007-10-30 15:57) [26]

- Перед вызовом SetWaitableTimer создать экз-р структуры TDataTimer
- Заполнить поле hTimer этой структуры хэндлом соотв.таймера
- Вызвать SetWaitableTimer, передав параметром указатель на этот экз-р
- В теле TimerAPCProc при необходимости уничтожить этот экз-р, ибо ссылка на него передана 1-м параметром и доступна.


 
Dmitry_177   (2007-10-30 16:08) [27]


> - Перед вызовом SetWaitableTimer создать экз-р структуры
> TDataTimer

если она объявлена в разделе описания переменных:

var
DataTimer: TDataTimer;


она разве не создана?


 
Сергей М. ©   (2007-10-30 16:13) [28]


> она разве не создана?
>


Создана.
В единственном экз-ре.

А у тебя куча объектов-таймеров, и каждый из них при таком решении нуждается в собственном экз-ре.


 
Dmitry_177   (2007-10-30 16:20) [29]

а как их тогда создавать?


 
Сергей М. ©   (2007-10-30 16:52) [30]

например, так:

PDataTimer = ^TDataTimer;

TDataTimer = packed record
..
end;

..
pdt: PDataTimer;

..

New(pdt);


 
Dmitry_177   (2007-10-30 17:09) [31]

Спасибо! соответственно и удалято тогда Dispose(pdt) ?


 
Сергей М. ©   (2007-10-30 17:13) [32]

разумеется !


 
Сергей М. ©   (2007-10-30 17:15) [33]

Только ведь в теле TimerAPCProc у тебя не будет никаких pdt, а будет 1-й параметр указательного типа, его и указывай в кач-ве параметра для Dispose


 
Dmitry_177   (2007-10-30 17:18) [34]

я так и понял :) спасибо!


 
Dmitry_177   (2007-10-30 18:59) [35]

Блин! Решил еще добавить событие на считывание новых значений из этого же файла.. SleepEx уже не спасает..


function ThreadEvent(Param: Pointer): DWORD; stdcall;
begin
 while true do
   begin
     if WaitForSingleObject(hEvent, INFINITE) = WAIT_OBJECT_0 then
       begin
         UninstallTimers;
         InstallTimers;
       end;
   end;
 Result := 0;
end;

...
 InstallTimers;

 hEvent := CreateEvent(nil, false, false, EventName);
 CloseHandle(CreateThread(nil, 0, @ThreadEvent, nil, 0, idThread));

 while true do
   SleepEx(INFINITE, True);


 
Dmitry_177   (2007-10-30 19:07) [36]

т.е. дело в том что событие не срабатывает.. сделал трассировку, в функции события ThreadEvent останавливается на WaitForSingleObject и все..


 
MetalFan ©   (2007-10-30 21:28) [37]

тебе не надоело на куче формов одно и то же писать? ))


 
Сергей М. ©   (2007-10-31 08:20) [38]


> SleepEx уже не спасает


> останавливается на WaitForSingleObject и все


У попа была собака..

Goto [4]


 
Dmitry_177   (2007-10-31 21:59) [39]

непонимаю всеравно в чем дело.. может этот SleepEx срабатывает первей и не дает сработать WaitForSingleObject-у в другом потоке?


 
Сергей М. ©   (2007-11-01 08:30) [40]

Причем здесь другой поток ?

SleepEx у тебя сработал ? Сработал.
TimerAPCProc вызывается при этом ? Вызывается.
Ответ на вопрос ты получил ? Получил.

Так в чем же дело ?



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

Текущий архив: 2008.08.03;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.023 c
2-1215148339
Забывчивый
2008-07-04 09:12
2008.08.03
Раздел finalization в DLL или из справки не понял


2-1214886949
DJ_UZer
2008-07-01 08:35
2008.08.03
Как считать текстовый файл из интерната


2-1215055645
prodex
2008-07-03 07:27
2008.08.03
Объясните разницу..


2-1214976925
lewka-serdceed
2008-07-02 09:35
2008.08.03
ключ в реестре


2-1214973707
uno-84
2008-07-02 08:41
2008.08.03
Несколько вопросов по StringGrid