Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> почему не срабатывает таймер? 
:(
    Опции темы
Dmitry_177
Дата 29.10.2007, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Есть 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.


Подскажите пожалуйста..
PM MAIL   Вверх
Alix
Дата 29.10.2007, 14:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


L45
**


Профиль
Группа: Участник
Сообщений: 581
Регистрация: 4.5.2005
Где: Pskov/Spb

Репутация: 3
Всего: 23



начнем с того, что ты не создаешь окна, а сообщения могут слаться только ему, так что цикл GetMessage просто не имеет смысла


--------------------
Знание только тогда знание, когда оно приобретено усилиями своей мысли, а не памятью (с) Л. Толстой
High tech. Low live. (с) Gardner Dozois
PM MAIL ICQ Skype   Вверх
Dmitry_177
Дата 29.10.2007, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



а как тогда быть?
PM MAIL   Вверх
maxim1000
Дата 29.10.2007, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



для того, чтобы вызывалась асинхронная процедура, нужно, чтобы поток был в прерываемом состоянии
например, можно использовать SleepEx


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 29.10.2007, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



А вот как сделать так чтобы все таймеры сработали? Что-то я не придумаю никак.. Может SleepEx в бесконечный цикл поставить? Ведь программа вылетает при первом же срабатывании..
PM MAIL   Вверх
Dmitry_177
Дата 29.10.2007, 23:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



я сделал в цикле 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
PM MAIL   Вверх
maxim1000
Дата 30.10.2007, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



а зачем делать SleepEx в цикле?
туда же сразу можно написать нужный период или INFINITE


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 30.10.2007, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



у меня какраз вот так:

Код

while true do
  SleepEx(INFINITE, True);


При вызове TimerAPCProc, SleepEx завершается..
PM MAIL   Вверх
MetalFan
Дата 30.10.2007, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



хм, продублирую и здесь)
Цитата(Dmitry_177 @  29.10.2007,  23:03 Найти цитируемый пост)
а в lpArgToCompletionRoutine обрезанная строка, т.е. например исходная такая: 29.10.2007 21:33:00 а в процедуре она такая: 29.10.2007 21:33 

словишь в конце-концов AV, если так оставишь.
у тебя Sections прибивается в InstallTimers....


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
maxim1000
Дата 30.10.2007, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



Цитата(Dmitry_177 @  30.10.2007,  10:03 Найти цитируемый пост)
При вызове TimerAPCProc, SleepEx завершается.. 

а... это я стормозил, документацию не прочитал...


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 30.10.2007, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Еще маленький вопросик, можно ли в TimerAPCProc определить какой таймер сработал? Ведь если таймер с периодом он так и будет дергать TimerAPCProc, так вот если уже больше он не понадобится, чтоб можно его было хлопнуть в этой же TimerAPCProc..
PM MAIL   Вверх
maxim1000
Дата 30.10.2007, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



а не проще ли использовать WaitForMultipleObjects?
там и, какой объект сработал, узнать проще простого, и всякие асинхронные процедуры не нужно городить...


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 30.10.2007, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



в ini файле время срабатывания может и не по порядку быть.. получится так что считается первым более позднее время срабатывания чем раннее?
PM MAIL   Вверх
Dmitry_177
Дата 30.10.2007, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Блин! Решил еще добавить событие на считывание новых значений из этого же файла.. 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);


Добавлено через 7 минут и 43 секунды
т.е. дело в том что событие не срабатывает.. сделал трассировку, в функции события ThreadEvent останавливается на WaitForSingleObject и все..
PM MAIL   Вверх
maxim1000
Дата 30.10.2007, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



Цитата(Dmitry_177 @  30.10.2007,  19:00 Найти цитируемый пост)
в функции события ThreadEvent останавливается на WaitForSingleObject и все..

так а кто ж его дёрнет, чтобы WaitForSingleObject вышла?


--------------------
qqq
PM WWW   Вверх
MetalFan
Дата 30.10.2007, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



кста, и почему bManualReset = false?


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Dmitry_177
Дата 30.10.2007, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Цитата

так а кто ж его дёрнет, чтобы WaitForSingleObject вышла?

в другой программе..
PM MAIL   Вверх
Dmitry_177
Дата 30.10.2007, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Цитата

кста, и почему bManualReset = false?

событие с автоматическим сбросом =)
PM MAIL   Вверх
MetalFan
Дата 31.10.2007, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Dmitry_177, а зачем? ) если "ожидатель" только один, то ладно.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
maxim1000
Дата 31.10.2007, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



Цитата(Dmitry_177 @  30.10.2007,  21:54 Найти цитируемый пост)
в другой программе..

ну, похоже на то, что программа та программа не дёргает...

Добавлено через 2 минуты и 46 секунд
кстати, а та программа только дёргает или тоже ждёт этого события?
просто если оно автоматически сбрасываемое, то может получиться так, что две программы ждут, оно дёргается, одна программа дожидается, событияеавтоматически сбрасывается, и вторая программа не дожидается...


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 31.10.2007, 19:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



не.. та именно дергает.. вот код из другой программы которая дергает:

Код

  hEvent := CreateEvent(nil, false, false, EventName);
  SetEvent(hEvent);
  CloseHandle(hEvent);


EventName - строковая константа, и там и там одна и таже..
PM MAIL   Вверх
MetalFan
Дата 31.10.2007, 20:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



Dmitry_177, а где проверка на возможные ошибки?


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Dmitry_177
Дата 31.10.2007, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



MetalFan, чтобы сократить код я их убрал, я показал сам смысл я в той программе дергаю это событие..
PM MAIL   Вверх
maxim1000
Дата 31.10.2007, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



хм... а не получается ли так:
1. первая программа создаёт событие
2. дёргает его
3. успевает удалить его до того, как его откроет вторая программа
4. вторая программа создаёт уже новое событие
и т.д.
?


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 31.10.2007, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Цитата

хм... а не получается ли так:
1. первая программа создаёт событие
2. дёргает его
3. успевает удалить его до того, как его откроет вторая программа
4. вторая программа создаёт уже новое событие
и т.д.
?

да нет.. не может быть такого в моем случае..

я вот думаю, может этот SleepEx срабатывает первей и не дает сработать WaitForSingleObject-у в другом потоке?
PM MAIL   Вверх
maxim1000
Дата 1.11.2007, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



в общем, лучше было бы выложить тут два текста программ, которые ведут себя вышеописанным способом, если они, конечно, не очень большие (тогда их стоит минимизировать с сохранением непонятного поведения)


--------------------
qqq
PM WWW   Вверх
Dmitry_177
Дата 1.11.2007, 01:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Ок, и так поехали:

первая программа, та которая устанавливает таймеры и реагирует на событие для считывания новых таймеров из файла(запущена постоянно):

Код

program TimeServ;

uses
  Windows,
  Messages,
  ShFolder,
  Classes,
  IniFiles,
  SysUtils;

const
  EventName = '{58F4D8A4-CAD7-46DA-A3D1-238B95659E68}';

type
  PDataTimer = ^TDataTimer;

  TDataTimer = packed record   // структура, адрес переменной которой передается в TimerAPCProc
    hTimer: THandle;
    StrDateTime: PChar;
  end;

var
  hEvent: THandle;
  idThread: DWORD;
  hTimers: array of THandle;
  StrFilePath: string;
  Sections: TStrings;

function GetStrFilePath: string;
var
  StrBuffer: array [0 .. MAX_PATH - 1] of Char;
  StrAppDataFolder: string;
begin
  ShGetFolderPath(0, CSIDL_APPDATA, 0, 0, StrBuffer);
  StrAppDataFolder := StrBuffer + '\TimeManager';
  if not DirectoryExists(StrAppDataFolder) then
    ForceDirectories(StrAppDataFolder);
  Result := StrAppDataFolder + '\TimeManager.ini';
end;

procedure TimerAPCProc(lpArgToCompletionRoutine: PDataTimer; dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;
begin
  with TIniFile.Create(StrFilePath) do
    try
      if MessageBox(0, PChar(ReadString(lpArgToCompletionRoutine.StrDateTime, 'Note', '') + #13#10#13#10 + 'Удалить это напоминание?'), 'Напоминание', MB_ICONQUESTION or MB_YESNO) = idYes then
        begin
          CancelWaitableTimer(lpArgToCompletionRoutine.hTimer);
          CloseHandle(lpArgToCompletionRoutine.hTimer);
          EraseSection(lpArgToCompletionRoutine.StrDateTime);
          Dispose(lpArgToCompletionRoutine);
        end;
    finally
      Free;
    end;
end;

procedure InstallTimers;
var
  iTimer: integer;
  sysTime: SYSTEMTIME;
  fTime: FILETIME;
  DataTimer: PDataTimer;
begin
  with TIniFile.Create(StrFilePath) 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);
              SystemTimeToFileTime(sysTime, fTime);
              LocalFileTimeToFileTime(fTime, fTime);
              New(DataTimer);
              DataTimer.hTimer := hTimers[iTimer];
              DataTimer.StrDateTime := PChar(Sections[iTimer]);
              SetWaitableTimer(hTimers[iTimer], TLargeInteger(fTime), Round(Frac(StrToDateTime(ReadString(Sections[iTimer], 'Period', '0'))) * 86400) * 1000, @TimerAPCProc, DataTimer, false);   // период записывается в формате DateTime, перевожу в миллисекунды
            end;
        end;
    finally
      Free;
    end;
end;

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

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;

begin
  StrFilePath := GetStrFilePath; 
  Sections := TStringList.Create;

  InstallTimers;

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

  while true do
    SleepEx(INFINITE, True);

  UninstallTimers;
  Sections.Free;
end.


теперь вторая, та которая записывает таймеры и дергает событие(запускается нерегулярно):
в ней в принципе ничего сложного нету, она записывает в файл таймеры, которые вводятся с использованием форм и по завершению дергает событие.. Я думаю саму запись ненужно показывать, приведу FormClose, который собственно и дергает событие:

Код

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);   // Close
var
  hEvent: THandle;
begin
  hEvent := CreateEvent(nil, false, false, EventName);
  if hEvent = INVALID_HANDLE_VALUE then
    Exit;
  if GetLastError = ERROR_ALREADY_EXISTS then
    SetEvent(hEvent);
  CloseHandle(hEvent);
end;


Код трассировал, SetEvent срабатывает, т.е. само событие 100% дергается..

Это сообщение отредактировал(а) Dmitry_177 - 1.11.2007, 01:27
PM MAIL   Вверх
dumb
Дата 1.11.2007, 04:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



Цитата(Dmitry_177 @  30.10.2007,  19:00 Найти цитируемый пост)
т.е. дело в том что событие не срабатывает..
подозреваю, что событие то срабатывает, а вот таймеры после переустановки - уже нет. и причина тому очевидна - ты устанавливаешь заново таймеры в рабочем потоке, который вовсе не находится в alertable-состоянии во время ожидания события hEvent.

надо сделать примерно так:
Код

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

begin
  StrFilePath := GetStrFilePath;
  Sections := TStringList.Create;
//  InstallTimers;
  hEvent := CreateEvent(nil, false, false, EventName);
  SetEvent(hEvent); // initial install timers
  hThread := CreateThread(nil, 0, @ThreadEvent, nil, 0, idThread);
  WaitForSingleObject(hThread, INFINITE);
  CloseHandle(hThread);
  UninstallTimers;
  Sections.Free;
end.

PM MAIL   Вверх
MetalFan
Дата 1.11.2007, 08:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 16
Всего: 128



давай код примера приложения в аттач... что так пальцем в небо тыкать...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Dmitry_177
Дата 1.11.2007, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Я сделал вот так:

Код

InstallTimers;

hEvent := CreateEvent(nil, false, false, EventName);
while true do
 begin
   if WaitForSingleObjectEx(hEvent, INFINITE, True) = WAIT_OBJECT_0 then
     begin
       UninstallTimers;
       InstallTimers;
     end;
 end;


и все заработало  smile 

кстати мы создаем в InstallTimers, структуры TDataTimer: New(DataTimer); удаляем их в TimerAPCProc: Dispose(lpArgToCompletionRoutine);.. А если время срабатывания будет удалено в той второй программе, то получается DataTimer не удалится?
PM MAIL   Вверх
Dmitry_177
Дата 5.11.2007, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



на самом деле как тогда удалять DataTimer? вот задам я таймер в той программе, в этой создастся DataTimer и установится таймер.. А потом в той программе удалю этот таймер.. то что будет с DataTimer? Как его удалять?
PM MAIL   Вверх
dumb
Дата 5.11.2007, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



Цитата(Dmitry_177 @  5.11.2007,  14:02 Найти цитируемый пост)
на самом деле как тогда удалять DataTimer?
тебе надо вместо массива хэндлов hTimers сделать массив(или там TList) DataTimer'ов. в таймерном callback'е "шерстить" этот массива на предмет переданного DataTimer, и удалять его - и самого и из массива.
PM MAIL   Вверх
Dmitry_177
Дата 8.11.2007, 01:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Цитата

в таймерном callback'е "шерстить" этот массива на предмет переданного DataTimer, и удалять его - и самого и из массива.

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

Это сообщение отредактировал(а) Dmitry_177 - 8.11.2007, 02:12
PM MAIL   Вверх
dumb
Дата 8.11.2007, 02:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 7
Всего: 158



Цитата(Dmitry_177 @  8.11.2007,  01:57 Найти цитируемый пост)
и получается так что в остальных таймерах ссылки на элементы массива сбиваются на один элемент.. 
э-э! я разве что-то говорил про передачу ссылки на элементы массива?! хотя согласен - немного неточно описал свою мысль. smile
имелось ввиду примерно следущее:
Код

var
  ...
  dta: TList;
//  hTimers: array of THandle;
...
procedure TimerAPCProc(lpArgToCompletionRoutine: PDataTimer; dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;
begin
  with TIniFile.Create(StrFilePath) do
    try
      if MessageBox(0, ...) = idYes then
        begin
          dta.Remove(lpArgToCompletionRoutine);
          CancelWaitableTimer(lpArgToCompletionRoutine.hTimer);
          CloseHandle(lpArgToCompletionRoutine.hTimer);
          EraseSection(lpArgToCompletionRoutine.StrDateTime);
          Dispose(lpArgToCompletionRoutine);
        end;
    finally
      Free;
    end;
end;
procedure InstallTimers;
var
  iTimer: integer;
  sysTime: SYSTEMTIME;
  fTime: FILETIME;
  DataTimer: PDataTimer;
begin
  with TIniFile.Create(StrFilePath) do
    try
      ReadSections(Sections);
      if Sections.Count > 0 then
        begin
          for iTimer := 0 to Sections.Count - 1 do
            begin
              New(DataTimer);
              DataTimer.hTimer := CreateWaitableTimer(nil, false, nil);
              DateTimeToSystemTime(StrToDateTime(Sections[iTimer]), sysTime);
              SystemTimeToFileTime(sysTime, fTime);
              LocalFileTimeToFileTime(fTime, fTime);
              DataTimer.StrDateTime := PChar(Sections[iTimer]);
              SetWaitableTimer(DataTimer.hTimer, TLargeInteger(fTime),
                               Round(Frac(StrToDateTime(ReadString(Sections[iTimer], 'Period', '0'))) * 86400) * 1000,
                               @TimerAPCProc, DataTimer, false);
              dta.Add(DataTimer);
            end;
        end;
    finally
      Free;
    end;
end;
procedure UninstallTimers;
var
  iTimer: integer;
  hTimer: THandle;
begin
  for iTimer := 0 to dta.Count - 1 do
    begin
      hTimer := PDataTimer(dta.Items[iTimer]).hTimer;
      CancelWaitableTimer(hTimer);
      CloseHandle(hTimer);
      Dispose(dta.Items[iTimer]);
    end;
  dta.Clear;
  Sections.Clear;
end;

...

begin
  dta := TList.Create;
  StrFilePath := GetStrFilePath;
...
  Sections.Free;
  dta.Free;
end.

PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1397 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.