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


Anatoly Podgoretsky   (2008-07-03 12:08:00) [21]

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

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


Anatoly Podgoretsky   (2008-07-03 12:08:00) [22]

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

Я не телепат.


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

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

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


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

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

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

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


Loginov Dmitry   (2008-07-03 11:59:00) [25]


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


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


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


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


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


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


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

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


Anatoly Podgoretsky   (2008-07-03 11:55:00) [27]

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

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


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


Anatoly Podgoretsky   (2008-07-03 11:53:00) [28]

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

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

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


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

> 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;


Loginov Dmitry   (2008-07-03 11:34:00) [30]


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


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


clickmaker   (2008-07-03 11:27:00) [31]

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

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

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


McSimm   (2008-07-03 11:27:00) [32]


> Loginov Dmitry ©   (03.07.08 11:06)


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

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

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

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


Riply   (2008-07-03 11:18:00) [33]

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

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

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


Loginov Dmitry   (2008-07-03 11:06:00) [34]


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


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


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


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


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

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

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

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

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


McSimm   (2008-07-03 11:02:00) [36]


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

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


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


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


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


Loginov Dmitry   (2008-07-03 10:48:00) [38]


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


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


McSimm   (2008-07-03 10:43:00) [39]

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


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

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


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

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

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


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

Наверх

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