Форум: "WinAPI";
Текущий архив: 2008.08.03;
Скачать: [xml.tar.bz2];
Внизпочему не срабатывает таймер? Найти похожие ветки
← →
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 вся ветка
Форум: "WinAPI";
Текущий архив: 2008.08.03;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.008 c