Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-10799
Gena_R
2003-08-22 10:21
2003.09.04
dll


1-10816
Zheks
2003-08-21 21:03
2003.09.04
После экзешника


14-10906
WASYA
2003-08-18 12:16
2003.09.04
Про интернет


14-10956
VEG
2003-08-13 17:51
2003.09.04
Дообновлял свою BIOS...


14-10904
KSergey
2003-08-18 12:35
2003.09.04
Про возможность





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский