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-05 09:04:00) [1]

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


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


GrayFace   (2008-07-05 03:01:00) [2]

Как я помню, сообщение 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;

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


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


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


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


Loginov Dmitry   (2008-07-03 20:13:00) [4]

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

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

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


MsGuns   (2008-07-03 18:43:00) [5]

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

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


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

MsGuns ©   (03.07.08 14:33) [55]

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


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

Microsoft Windows CE 3.0 ?

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


MsGuns   (2008-07-03 14:33:00) [8]

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

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

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

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


Loginov Dmitry   (2008-07-03 14:16:00) [9]


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


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


Leonid Troyanovsky   (2008-07-03 14:01:00) [10]


> 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 13:53:00) [11]


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


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


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


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

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


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


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


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


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

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


McSimm   (2008-07-03 13:38:00) [15]

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

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

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

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


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

> 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 12:54:00) [17]


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


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

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


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


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

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

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

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


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


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

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

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


Loginov Dmitry   (2008-07-03 12:15:00) [20]

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


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

Наверх

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