Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Загоны с таймером


Страницы:   1 2 3 4

Loginov Dmitry ©   (2008-07-02 23:50:00) 

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


procedure TMyForm.MyTimerTimer(Sender: TObject);
begin
 ALog.LogStr('before MyTimerTimer');
 MyTimer.Enabled := False;
 Sleep(10); // реально здесь выполняется ряд "полезных" действий
 ALog.LogStr('after MyTimerTimer');
end;


по умолчанию MyTimer.Enabled=False
MyTimer.Interval=50

В событии FormShow на ряду с прочими "полезными" действиями осуществляется вызов MyTimer.Enabled := True;

Собственно все. В логе при этом вижу следующее:

before MyTimerTimer
after MyTimerTimer
before MyTimerTimer
after MyTimerTimer
before MyTimerTimer
after MyTimerTimer


т.е. таймер вместо одного раза срабатывает 3 раза.
С этим столкнулся на работе. Дома ситуация не воспроизводится.

Компилю на Delphi2007 SP2 с пакетами.

Мое мнение насчет причины данной проблемы такое: В событии FormShow после вызова MyTimer.Enabled := True продолжается инициализация, вешающая основной поток некоторое время, в течение которого в очередь окна таймера успевает поступить 3 сообщения WM_TIMER, и установка MyTimer.Enabled=False не в силах повлиять на это. Однако пытаюсь эмулировать задержку в FormShow дома (Delphi7) - никаких проблем не возникает. Как ни бьюсь, OnTime вызывается только один раз. Завтра разбирусь с этим вопросом, однако может кто-нибудь с этим уже разбирался, где правда?


Loginov Dmitry   (2008-07-03 10:36:00) [41]


> Почему Винда должна это проверять - тоже непонятно. Таймер
> тикнул - сообщение поступило.


См. [8]


> Не ищи ошибки в Виндоус, она не там, Юрий уже сказал где
> искать, но там ты начинаешь искать в последнею очередь,
> поэтому у тебя очень много подобных веток.


Ладно. Пусть каждый останется при своем мнении. Я вывод для себя сделал. Вы для себя. Бестолку стараться кого-то в чем-то убедить.
Проблему исправил путем переноса обращений к DCOM на строку выше, чем включение таймера. Пре проблемы решились. Спасибо за содействие!


Anatoly Podgoretsky   (2008-07-03 10:28:00) [42]

около 200 мс и время таймера 50 мс и блокирование таймера не сразу а после выполнения чего то в какой то неизвестной процедуре.

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


MsGuns   (2008-07-03 10:27:00) [43]

>Loginov Dmitry ©   (03.07.08 10:15) [17]
>Таймер связан с очередью сообщений.

Еще раз спрашиваю КАКИМ БОКОМ ?

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


Юрий Зотов   (2008-07-03 10:24:00) [44]

> Loginov Dmitry ©   (03.07.08 09:48) [14]

> Глюк был в DCOM (получается, что все-таки винда глючит!

А теперь разберемся, действительно ли это так.

> После установки в FormShow
> MyTimer.Enabled=True
> происходит обращение к DCOM, которое длится некоторое время
> (в моем случае около 200 мс).

Где тут глюк DCOM - непонятно. Пока что его не видно.

> Пока происходит данное обращение, винда кладет WM_TIMER в очередь

Где тут глюк DCOM - снова непонятно. Пока что его все еще не видно.

> и не проверяет, есть ли уже данное сообщение в очереди.

Почему Винда должна это проверять - тоже непонятно. Таймер тикнул - сообщение поступило. Ну а уж DCOM тут совсем никаким боком.

Возвращаемся к исходному утверждению:
> Глюк был в DCOM (получается, что все-таки винда глючит!

Дима, извини за самоцитату, но придется. Вот что я когда-то написал в "уроках для начинающих" (притом, большими буквами и с восклицательными знаками - обрати внимание):

"И ЗАПОМНИТЕ НА ВСЮ СВОЮ ОСТАВШУЮСЯ ПРОГРАММИСТСКУЮ ЖИЗНЬ - ВО ВСЕХ ГЛЮКАХ ВИНИТЕ СНАЧАЛА СЕБЯ, А УЖ ПОТОМ МАШИНУ, СИСТЕМУ, DELPHI И СОСЕДА ДЯДЮ ВАСЮ. И ошибку ВСЕГДА ищите прежде всего в СВОЕЙ программе!!! И чем чаще Вы будете нарушать это железное правило - тем больше времени и нервов Вы будете тратить на поиск и устранение ошибок. С момента появления первой ЭВМ этот закон проверен уже миллионы раз, всеми поколениями программистов, на всех машинах системах и языках".


Loginov Dmitry   (2008-07-03 10:19:00) [45]


> просто удивительно, если оно присуще ПРАКТИКУ, призванному
> прежде всего решать ПРАКТИЧЕСКИЕ задачи.


Хотелось просто для себя самого убедиться, что не я глючу.


Loginov Dmitry   (2008-07-03 10:15:00) [46]


> Каким боком таймер имеет отношнние к DCOMу ?


Таймер связан с очередью сообщений. DCOM - тоже. Вот такое отношение и выливается в bug.


MsGuns   (2008-07-03 10:10:00) [47]

Офигеть ! Каким боком таймер имеет отношнние к DCOMу ?

Разбирательство ради самого разбирательства есть чистейший мазохизм и просто удивительно, если оно присуще ПРАКТИКУ, призванному прежде всего решать ПРАКТИЧЕСКИЕ задачи.


Игорь Шевченко   (2008-07-03 10:05:00) [48]


> получается, что все-таки винда глючит!


Руки выпрями и винда перестанет глючить


Loginov Dmitry   (2008-07-03 09:48:00) [49]

Разобрался. Глюк был в DCOM (получается, что все-таки винда глючит! :). После установки в FormShow

MyTimer.Enabled=True

происходит обращение к DCOM, которое длится некоторое время (в моем случае около 200 мс). Пока происходит данное обращение, винда кладет WM_TIMER в очередь и не проверяет, есть ли уже данное сообщение в очереди. Всех тонкостей я не знаю, но с виду выглядет именно так. Если увеличить время вызываемой по DCOM функции, то увеличится число срабатываний таймера. В лог у меня вывелось следующее (Sleep(10) я убрал):


03.07.2008 09:47:38.980 PlatezTimer.Enabled := True
03.07.2008 09:47:41.889 End of FormShow
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.889 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] Before PlatezTimerTimer!
03.07.2008 09:47:41.905 [информ.] After PlatezTimerTimer!


т.е. все сообщения WM_TIMER обработались скопом.


Anatoly Podgoretsky   (2008-07-03 07:46:00) [50]

> Loginov Dmitry  (03.07.2008 7:42:12)  [12]

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


Loginov Dmitry   (2008-07-03 07:42:00) [51]

> Я бы еще это проверил, не визуально, а прямо перед установкой
> в true в обработчике.


врядли. Но проверю.


> Измениться может много, ведь содержимое процедуры неизвестно,
> возможно пока она работает успевает прийти еще одно сообщение,
> два не может Виндоус не позволит.


Теоретически может, но врядли. LogStr отрабатывает очень быстро (не более 1 мс), а у таймера таймаут 50 мс.

P.S. Не удивлюсь, есть откроется очередной косяк в винде ;)))
... или где-то в программе (все равно не удивлюсь)


Anatoly Podgoretsky   (2008-07-03 00:52:00) [52]

> Loginov Dmitry  (03.07.2008 0:49:09)  [9]

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


McSimm   (2008-07-03 00:50:00) [53]


> по умолчанию MyTimer.Enabled=False

Я бы еще это проверил, не визуально, а прямо перед установкой в true в обработчике.


Loginov Dmitry   (2008-07-03 00:49:00) [54]

> Местами менять не пробовал.


А что должно измениться? В лог оно так и так запишет, никуда не денется.


Loginov Dmitry   (2008-07-03 00:47:00) [55]

> Или их отсеивает DispatchMessage


Все-таки в MSDN пишут точнее:
Timers expire at regular intervals, but a timer that expires multiple times before being serviced does not generate multiple WM_TIMER messages.


Anatoly Podgoretsky   (2008-07-03 00:43:00) [56]

> Loginov Dmitry  (02.07.2008 23:50:00)  [0]

ALog.LogStr('before MyTimerTimer');
MyTimer.Enabled := False;

Местами менять не пробовал.


Loginov Dmitry   (2008-07-03 00:35:00) [57]

> У Вас, ув.Дмитрий, просто таки талант даже для самых простых
> задач искать и находить головоломные решения ;)


Обойти проблему - нужно несколько секунд. Но хотелось бы понять причину, чтоб впредь на подобном не спотыкаться.


Loginov Dmitry   (2008-07-03 00:32:00) [58]

> Видимо одновременно в очереди сообщений не может быть двух
> WM_TIMER для одного и того же таймера.


Или их отсеивает DispatchMessage (куды они еще могут деваться?)


MsGuns   (2008-07-03 00:29:00) [59]

У Вас, ув.Дмитрий, просто таки талант даже для самых простых задач искать и находить головоломные решения ;)


Loginov Dmitry   (2008-07-03 00:21:00) [60]

> А FormShow точно один раз только вызывается ?


С этого-то я и начал со всем этим разбираться. FormShow вызывается только 1 раз.


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо