Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.009 c
2-1215064983
zdm77
2008-07-03 10:03
2008.08.03
поиск в WORD


15-1213606446
9899100
2008-06-16 12:54
2008.08.03
Виртуальный логический диск


4-1193628432
031178
2007-10-29 06:27
2008.08.03
Как программно поменять частоту обновления экрана


4-1193915862
fedormoore
2007-11-01 14:17
2008.08.03
сканер


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





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский