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

Вниз

Загоны с таймером   Найти похожие ветки 

 
Loginov Dmitry ©   (2008-07-02 23:50) [0]

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


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 вызывается только один раз. Завтра разбирусь с этим вопросом, однако может кто-нибудь с этим уже разбирался, где правда?


 
McSimm ©   (2008-07-03 00:07) [1]

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


 
Loginov Dmitry ©   (2008-07-03 00:20) [2]

В принципе
The KillTimer function does not remove WM_TIMER messages already posted to the message queue.
Но все равно эмуляция данного "эффекта" на чистом проекте не получается :(
Делаю следующее:

procedure TForm1.FormShow(Sender: TObject);
begin
 MyTimer.Enabled := True;
 sleep(1000);
end;

Ловится только одно WM_TIMER, хотя за 1 секунду их должно было накопиться 20 штук. Видимо одновременно в очереди сообщений не может быть двух WM_TIMER для одного и того же таймера. А работе наверно именно это и происходит.
Бред какой-то :(


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

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


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


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

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


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

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


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


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

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


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


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

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

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

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


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

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


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


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

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


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


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


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

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


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

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

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


 
Loginov Dmitry ©   (2008-07-03 07:42) [12]

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


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


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


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

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


 
Anatoly Podgoretsky ©   (2008-07-03 07:46) [13]

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

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


 
Loginov Dmitry ©   (2008-07-03 09:48) [14]

Разобрался. Глюк был в 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 обработались скопом.


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


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


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


 
MsGuns ©   (2008-07-03 10:10) [16]

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

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


 
Loginov Dmitry ©   (2008-07-03 10:15) [17]


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


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


 
Loginov Dmitry ©   (2008-07-03 10:19) [18]


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


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


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

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

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

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

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

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

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

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

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

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

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

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

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


 
MsGuns ©   (2008-07-03 10:27) [20]

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

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

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


 
Anatoly Podgoretsky ©   (2008-07-03 10:28) [21]

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

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


 
Loginov Dmitry ©   (2008-07-03 10:36) [22]


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


См. [8]


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


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


 
MsGuns ©   (2008-07-03 10:39) [23]

>Проблему исправил путем переноса обращений к DCOM на строку выше, чем включение таймера. >Пре проблемы решились.

Ага. На смену им придут проблемищи


 
McSimm ©   (2008-07-03 10:43) [24]

А если заменить вызов DCOM на любую другую работу равной длительности, то проблема не воспроизводится ?


> Юрий Зотов ©   (03.07.08 10:24) [19]

Так не должны вроде сообщения таймера накапливаться, пока первое не обслужено? А тут похоже накапливаются.


 
Loginov Dmitry ©   (2008-07-03 10:48) [25]


> А если заменить вызов DCOM на любую другую работу равной
> длительности, то проблема не воспроизводится ?


проблема возникает только при вызове DCOM-функции.
установка Sleep() тойже длительности к ошибке не приводит. Пытался по всякому, даже комбинировал с ProcessMessages.


 
Loginov Dmitry ©   (2008-07-03 10:51) [26]


> проблема возникает только при вызове DCOM-функции.


причем не важно какой функции. Работаю через TDCOMConnection. С проблемой столкнулся при открытии набора данных с помощью TClientDataSet.Open (200 мс как раз на это уходило). Но точно также ошибка воспроизводится при вызове любой "медленной" функции через TDCOMConnection.AppServer


 
McSimm ©   (2008-07-03 11:02) [27]


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

А как конфигурации отличаются, интересно ?


 
Юрий Зотов ©   (2008-07-03 11:03) [28]

> McSimm ©   (03.07.08 10:43) [24]

> Так не должны вроде сообщения таймера накапливаться,
> пока первое не обслужено? А тут похоже накапливаются.

А разве оно не обслужено?

Из очереди оно выбрано? Да.
Из очереди оно удалено? Да (и этого уже достаточно).
В WndProc поступило? Да.
По завершении обработки Msg.Result равно нулю? Да.


 
Loginov Dmitry ©   (2008-07-03 11:06) [29]


> А как конфигурации отличаются, интересно ?


Я только вчера TClientDataSet.Open на работе добавил. Дома просто была "устаревшая" версия исходников.


> А разве оно не обслужено?


Нет. Это видно из лога в [14]


 
Riply ©   (2008-07-03 11:18) [30]

> [16] MsGuns ©   (03.07.08 10:10)
> Разбирательство ради самого разбирательства есть чистейший мазохизм и просто удивительно,
> если оно присуще ПРАКТИКУ, призванному прежде всего решать ПРАКТИЧЕСКИЕ задачи.

"Разбирательство" помогает понять суть происходящего и не допускать
обидных и досадных ляпов в будущем.
Грош цена "ПРАКТИКУ", который, столкнувшись с непонятной ему вещью,
путем шаманства (потому что не понял) убирает странный эфект и идет дальше.

IMHO разумеется.


 
McSimm ©   (2008-07-03 11:27) [31]


> Loginov Dmitry ©   (03.07.08 11:06)


Можно было бы еще предположить, что логирование блокируется. Хотя обычно логирование добавляют, когда проблема уже есть...

Но в принципе флоу может выглядеть так:

Таймер активирован.
Поступает сообщение WM_TIMER
Обрабатывается сообщение (обработано), вызывается логирование и застряет
Поступает сообщение
Обрабатывается сообщение (обработано), вызывается логирование и застряет
...

Заканчивается работа с DCOM
Убирается (каким-то образом) блокировка
Все ожидавшие возможности записать - записывают.
При этом таймер деактивируется


 
clickmaker ©   (2008-07-03 11:27) [32]

> Если вы по событию таймера (который вообще-то сам по себе)

вообще-то, не сам по себе
потому как

An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.

(c) MSDN


 
Loginov Dmitry ©   (2008-07-03 11:34) [33]


> Можно было бы еще предположить, что логирование блокируется.
>  Хотя обычно логирование добавляют, когда проблема уже есть.
> ..


Добавление логгирования было связано с возникновением данной проблемы.


 
Юрий Зотов ©   (2008-07-03 11:43) [34]

> Loginov Dmitry ©   (03.07.08 11:06) [29]

Когда срабатывает обработчик события OnTimer, вызвавшего его сообщения WM_TIMER в очереди УЖЕ нет. То есть, никакого накопления быть не может.

function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
...
begin
 ...
 if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
 begin
   ... // Здесь сообщение УЖЕ удалено из очереди (из-за PM_REMOVE)
   TranslateMessage(Msg);
   DispatchMessage(Msg); // И только теперь будет вызван обработчик
   ...
 end;
end;

Напиши обработчик по-человески и забудь о "глюках":

procedure TMyForm.MyTimerTimer(Sender: TObject);
begin
 MyTimer.Enabled := False;
 try
   ... // Здесь делай что угодно и сколько угодно, только не трогай таймер
 finally
   MyTimer.Enabled := True;
 end;
end;


 
Anatoly Podgoretsky ©   (2008-07-03 11:53) [35]

> Loginov Dmitry  (03.07.2008 10:36:22)  [22]

> Бестолку стараться кого-то в чем-то убедить.

Если бы я пытался, только в чем убеждать в статистике, так это же не вопрос.


 
Anatoly Podgoretsky ©   (2008-07-03 11:55) [36]

> McSimm  (03.07.2008 10:43:24)  [24]

Ты неправильно интерпритируешь ситуацию


begin
   Log; Вот тут приходит новое сообщение и так далее. И ничего не накапливается.
   Enabled:= False: Рано или поздно вот это отработает и шторм прекратится.


 
Loginov Dmitry ©   (2008-07-03 11:58) [37]


> Когда срабатывает обработчик события OnTimer, вызвавшего
> его сообщения WM_TIMER в очереди УЖЕ нет. То есть, никакого
> накопления быть не может.


Именно этого сообщения в очереди нет. Но есть другие (вопреки MSDN)


> Напиши обработчик по-человески и забудь о "глюках":


Вот именно так "по-человечески" оно и было. И глючило.

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


 
Loginov Dmitry ©   (2008-07-03 11:59) [38]


> Ты неправильно интерпритируешь ситуацию
>
>
> begin
>    Log; Вот тут приходит новое сообщение и так далее. И
> ничего не накапливается.
>    Enabled:= False: Рано или поздно вот это отработает и
> шторм прекратится.


Анатолий, я эти строки давно поменял местами. Это ничего не дало.


 
Юрий Зотов ©   (2008-07-03 12:01) [39]

> Loginov Dmitry ©   (03.07.08 11:58) [37]

> Именно этого сообщения в очереди нет. Но есть другие (вопреки MSDN)

Почему "вопреки"?


 
Anatoly Podgoretsky ©   (2008-07-03 12:07) [40]

> Loginov Dmitry  (03.07.2008 11:58:37)  [37]

Если этого сообщения нет, то как Виндоус может объеденить?
Это же не Копперфильдовские фокусы.


 
Anatoly Podgoretsky ©   (2008-07-03 12:08) [41]

> Loginov Dmitry  (03.07.2008 11:59:38)  [38]

Я не телепат.


 
Anatoly Podgoretsky ©   (2008-07-03 12:08) [42]

> Юрий Зотов  (03.07.2008 12:01:39)  [39]

Конечно не вопреки, а строго в соответствии с MSDN


 
Loginov Dmitry ©   (2008-07-03 12:15) [43]

в соответствии с MSDN: если для данного таймера уже есть сообщение WM_TIMER в очереди, то новые сообщения WM_TIMER для того же самого таймера в очередь не заносятся, пока не будет обработано первое сообщение WM_TIMER. Или я неверно интерпретирую MSDN?


 
McSimm ©   (2008-07-03 12:19) [44]


> пока не будет обработано первое сообщение WM_TIMER

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

Впрочем, я не вижу, чтобы это относилось к данному случаю


 
Юрий Зотов ©   (2008-07-03 12:42) [45]

> Loginov Dmitry ©   (03.07.08 12:15) [43]

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

Еще раз: в очереди его уже нет. Раз сработал обработчик OnTimer (а он сработал), то вызвавшее его сообщение WM_TIMER из очереди уже удалено.


 
McSimm ©   (2008-07-03 12:54) [46]


> Еще раз: в очереди его уже нет. Раз сработал обработчик
> OnTimer (а он сработал), то вызвавшее его сообщение WM_TIMER
> из очереди уже удалено.
>


Юрий, он имеено так и сказал:

> > Именно этого сообщения в очереди нет. Но есть другие (вопреки
> MSDN)


И судя по логам (я не склонен расценивать всю это ветку как мистификацию), очень похоже, что так и происходит - на момент обработки одного сообщения в очереди есть также и другие 19 штук. Что, если я не ошибаюсь, действительно противоречит MSDN


 
Юрий Зотов ©   (2008-07-03 13:26) [47]

> McSimm ©   (03.07.08 12:54) [46]

В логе написано, что обработчик OnTimer был вызван N раз подряд.  Больше в логе не написано ничего.

Но N идущих подряд вызовов обработчика OnTimer НЕ означают, что в очереди одновременно присутствовало несколько сообщений WM_TIMER.

1. В очередь поступает сообщение WM_TIMER.

2. Оно выбирается и удаляется из очереди (и с этого мгновения ничто не мешает приходу в очередь нового сообщения WM_TIMER).

3. Вызывается обработчик события OnTimer (а в очереди, возможно, уже есть новое сообщение WM_TIMER, либо оно может поступить туда во время выполнения кода обработчика).

4. В обработчике события пишется лог.

Как видим, эта последовательность действительно может повторяться. И в логе действительно будет написано, что обработчик события OnTimer сработал N раз подряд - что вовсе не означает накопления сообщений в очереди WM_TIMER.


 
McSimm ©   (2008-07-03 13:38) [48]

Мне кажется, что в таком случае лог был бы другим.

Там есть временные отметки есть - практически одномоментно выполняются два десятка сообщений.
Кроме того, мне кажется, что последовательность записей в логе была бы иной, т.е. сначала 20 Before а потом 20 After.
А тут мы видим, что после After (т.е. таймер уже деактивирован)  еще куча обработок происходит, при этом таймер по приведенному коду повторно не активируется. Да и нет задержки 50 мс, даже если где-то активируется в неприведенном коде.

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

Но разобраться хотелось бы. У меня всегда всякое необъясненное чешется :)


 
Loginov Dmitry ©   (2008-07-03 13:42) [49]

Мне удалось сделать минимальное приложение без единой кнопки, в котором данная проблема отлично воспроизводится. Ошибка действительно из-за DCOM.
Если кому хочется проверить, могу скинуть на мыло.


 
Loginov Dmitry ©   (2008-07-03 13:47) [50]


> Но разобраться хотелось бы. У меня всегда всякое необъясненное
> чешется


Отправил пример на adm@delphimaster.ru


 
Anatoly Podgoretsky ©   (2008-07-03 13:48) [51]


> McSimm ©   (03.07.08 13:38) [48]

А нет ли там потоков случайно, прямо или косвенно.


 
Loginov Dmitry ©   (2008-07-03 13:53) [52]


> Отправил пример на adm@delphimaster.ru


Не знаю, дошло ли оно. На всякий случай выслал еще одно с паролем.


 
Leonid Troyanovsky ©   (2008-07-03 14:01) [53]


> Loginov Dmitry ©   (03.07.08 12:15) [43]

> для того же самого таймера в очередь не заносятся, пока
> не будет обработано первое сообщение WM_TIMER. Или я неверно
> интерпретирую MSDN?

Плиз, уточни интерпретируемую статью.

AFAIK, окну не передаются WM_TIMER, WM_PAINT, WM_QUIT,
_до тех пор_, пока не будут обработаны более приоритетные сообщения.
Про WM_PAINT известно, что несколько из присутствующих
в очереди объединяют. А вот про выбрасывание из очереди
experied WM_TIMER я чего-то не припомню.

--
Regards, LVT.


 
Loginov Dmitry ©   (2008-07-03 14:16) [54]


> Плиз, уточни интерпретируемую статью.


http://msdn.microsoft.com/en-us/library/ms927685.aspx


 
MsGuns ©   (2008-07-03 14:33) [55]

>Riply ©   (03.07.08 11:18) [30]
>"Разбирательство" помогает понять суть происходящего и не допускать
>обидных и досадных ляпов в будущем.

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

>Грош цена "ПРАКТИКУ", который, столкнувшись с непонятной ему вещью,
>путем шаманства (потому что не понял) убирает странный эфект и идет дальше.

Грош цена повару, который чтобы убедиться, что борщ пересолен (недосолен) не слопает весь котел


 
Юрий Зотов ©   (2008-07-03 14:34) [56]

Microsoft Windows CE 3.0 ?

http://msdn.microsoft.com/en-us/library/ms644901(VS.85).aspx


 
Игорь Шевченко ©   (2008-07-03 17:37) [57]

MsGuns ©   (03.07.08 14:33) [55]

Плохому учишь. Зря


 
MsGuns ©   (2008-07-03 18:43) [58]

>Игорь Шевченко ©   (03.07.08 17:37) [57]
>Плохому учишь. Зря

Забыл добавить имху


 
Loginov Dmitry ©   (2008-07-03 20:13) [59]

Если кому еще интересно:

http://matrix.kladovka.net.ru/dcomandtimersrc.zip  (39 Кб, исходники)

http://matrix.kladovka.net.ru/dcomandtimer.zip (546 Кб, исходники и EXE)


 
Игорь Шевченко ©   (2008-07-03 23:31) [60]


> Если кому еще интересно:


запусти Spy++ или WinSignt и посмотри, какие сообщения каким окнам приходят, узнаешь много интересного.


 
GrayFace ©   (2008-07-05 03:01) [61]

Как я помню, сообщение WM_TIMER в нормальном случае в очередь не поступает, а передается оконной процедуре при выборке сообщений, если установлен флаг. (или я путаю с WM_PAINT?) Есть только мысль, что в DCOM все сообщения берутся из очереди, а потом возвращяются в нее без учета этой особенности.

Юрий Зотов ©   (03.07.08 11:43) [34]
Напиши обработчик по-человески и забудь о "глюках":

procedure TMyForm.MyTimerTimer(Sender: TObject);
begin
MyTimer.Enabled := False;
try
  ... // Здесь делай что угодно и сколько угодно, только не трогай таймер
finally
  MyTimer.Enabled := True;
end;
end;

Почему это более "по-человечески"? Иногда лучше так, иногда по-простому. У меня, вроде, не было ситуации, когда такое полезно.


 
Loginov Dmitry ©   (2008-07-05 09:04) [62]

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


Наверно так и есть. Ведь есть же костыль, когда в обработчике SendMessage(), вызванном из дополнительного потока (понято о чем речь? :)) нельзя вызывать функции DCOM (вернее, пока такой обработчик не отработает, вообще ниоткуда нельзя обращаться к DCOM). Так может и с таймером что-то из той же оперы.



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

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

Наверх




Память: 0.66 MB
Время: 0.024 c
2-1215153307
Максим В.
2008-07-04 10:35
2008.08.03
Pointer + Integer


15-1213518786
Галинка
2008-06-15 12:33
2008.08.03
Canon Pixma iP2500


2-1215104995
blazerad
2008-07-03 21:09
2008.08.03
ShowMessage


15-1213558693
Pavia
2008-06-15 23:38
2008.08.03
Современные компьютерные технологии


15-1213964364
AEN
2008-06-20 16:19
2008.08.03
Автошколы в Москве