Форум: "Основная";
Текущий архив: 2003.09.04;
Скачать: [xml.tar.bz2];
ВнизОбъясните, пожалуйста, про события... Найти похожие ветки
← →
Makhanev A.S. (2003-08-22 00:33) [0]Есть обработчик события.
В нём выполняется длительная операция с вызовом ProcessMessages.
Что происходит при повторной генерации события?
Обработчики (один и тот же обработчик одного и того же события) "становятся в очередь" или текущий прерывается и начинается новый?
Я экспериментировал.. до конца так и не понял, как в одном потоке всё это работает.
Буду благодарен за разъяснения, т.к. в моих книжкам про такое не пишут:(
← →
Ihor Osov'yak (2003-08-22 00:49) [1]Обработчики - это процедуры, вернее методы.. То есть они ни "прерватся", ни "в очередь" стать не могут.. А вот сами себя через неявную рекурсию вызвать - вполне могут..
вот, такой пример (брось на формочку бутон и мемо)
WM_MyMessage = = WM_USER + bla_bla;
TMyForm = class(TForm)
...
procedure WMMyMessage(var Msg:TMessage); message WM_MyMessage;
...
end;
...
var glob_idx: integer;
procedure TMyForm.WMMyMessage(var Msg:TMessage);
var idx: integer;
begin
idx := glob_idx;
inc(glob_idx);
if glob_idx > 5 then exit;
Memo1.Add("Enter: "+IntToStr(idx));
PostMessage(Handle, WM_MyMessage, 0, 0);
Application.ProcessMessages;
Memo1.Add("Exit: "+IntToStr(idx));
end;
procedure TMyForm.Button1Click(Sender: TObject);
begin
PostMessage(Handle, WM_MyMessage, 0, 0);
end;
Запусти на выполнение, щелкни на кнопочку - и понаблюдай за текстом, который в мемо появился..
.. Ты наблюдаешь неявную рекурсию..
.. продолжение следует..
← →
Ihor Osov'yak (2003-08-22 01:00) [2]Собственно, что здесь происходит, и почему рекурсия возникает..
WMMyMessage посылает сообщение в очередь -
PostMessage(Handle, WM_MyMessage, 0, 0);
Но Application.ProcessMessages сразу же запускает цыкл выборки сообщений, где рано или позно доходит до WM_MyMessage, и естественно снова будет вызван
procedure TMyForm.WMMyMessage(var Msg:TMessage);
причем еще до выполнения
Memo1.Add("Exit: "+IntToStr(idx));
в вышестоящем "TMyForm.WMMyMessage"....
То есть имеем неявную рекурсию.. И для этого в примере есть условие на прерывание этой рекурсии -
if glob_idx > 5 then exit;
да, вернее нужно было
procedure TMyForm.Button1Click(Sender: TObject);
begin
glob_idx := 0;
PostMessage(Handle, WM_MyMessage, 0, 0);
end;
чтобы наблюдать эту рекурсию при каждом щелчке на бутон..
Зы. Иногда такая рекурсия делается специально.. Но значительно чаще начинающие при юзании Application.ProcessMessages где надо и где не надо на это нарываются, и не могут что с их творением происходит..
Зы2. Поэтому я всегда говорю начинающим - никогда не используйте Application.ProcessMessages и синхронайз, пока в тонкостях не будете понимать, что они делают..
А относительно синхронайз - то это, имхо, маленькая диверсия со стороны Борданд :-) Но это уже совсем другой разговор..
← →
Makhanev A.S. (2003-08-22 01:07) [3]То, что Вы написали про рекурсию я прекрасно понимаю.
Меня волнует следубщий аспект:
есть обработчик. Пока он работает опять герерируется "его" событие (к примеру, 2-ды нажали на кнопку).
Вопрос: что происходит?
По идее обработчик должен отработать дважды. Так и происходит, если в нём нет ProcessMessages.
Ставим ProcessMessages и видим: текущий обработчик прерывается, работает новый обработчик до конца, затем возобновляется первый обработчик.
В вышесказанном меня только что убедил следующи эксперимент.
Это всё очень легко смотрится на примере:
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
i:=0;
repeat
inc(i);
Caption := IntToStr(i);
Application.ProcessMessages; //если убрать, то всё выполняется последовательно.
until i = 3000;
end;
Вопрос: я правильно понял данный механизм?
← →
Rouse_ (2003-08-22 01:19) [4]В данном примере если убрать Application.ProcessMessages;
начинается процедура обработка события без выборки внешних сообщений (пока не завершится цикл - приложение просто не будет реагировать). Выводы делайте сами.
Желаю успехов
← →
Ihor Osov'yak (2003-08-22 01:19) [5]А я тебе не о том ли самом расказывал?
С той только разностью, что сообщение в моем примере генерирует сам метод, а ты дважды жмешь кнопарь.. В том и том случае сообщение попадает в очередь.. А Application.ProcessMessages запускает выборку и обработку этого сообщения (и не только его, а всех, что подвернутся) - до завершения твоего метода.. И вполне может быть ситуация, что результатом обработки какого-то сообщения может быть повторный вызов твоего метода..
Зы - только не прерывается он.. Это некорректное использование термина в этой ситуации..
Поставь точку останова в методе и понаблюдай за стеком при перврм и втором вызове.. Может чего и прояснится.. Или скомпилируй с отладочнвми dcu и по F7 вызов Application.ProcessMessages протрассируй.. Если терпения хватит :-).. Да, но про F7 применительно к Application.ProcessMessages это быстрее издевка, чем совет..
← →
Makhanev A.S. (2003-08-22 01:24) [6]
> Ihor Osov"yak © (22.08.03 01:19) [5]
Я Вас понял.
Прошу прощения за некорректность в формулировках.
Спасибо, Вы сумели объяснить мне это с помощью ProcessMessages.
Я часто имею дело с рекурсией, поэтому усвоить данный материал было несложно. Просто до возможности наличия неявной рекурсии при вызове обработчика я недодумался.
Спасибо!
← →
Rouse_ (2003-08-22 01:25) [7]Вдогонку к > Ihor Osov"yak © (22.08.03 01:19)
Application.ProcessMessages
в основном представляет из себя банальное принудительное
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
немного правильней использовать (зависит от структуры)PeekMessage
и обработчик
Желаю успехов
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.09.04;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.01 c