Форум: "Основная";
Текущий архив: 2003.09.01;
Скачать: [xml.tar.bz2];
ВнизКак можно запретить вызов even ta пока не отработал другой event Найти похожие ветки
← →
SergP (2003-08-15 21:12) [0]есть несколько компонентов. Для обработки их событий есть соответствующие обработчики. Но при работе проги бывает что в процессе работы одного обработчика вызывается другой. Как это можно предотвратить?
Например в одном объекте произошло событие A. Как мне запретить вызов обработчика событий Б этого или другого объекта, пока не отработал A?
А то ИМНО из-за этого иногда вылазят ошибки типа Access violation .....
← →
Романов Р.В. (2003-08-15 21:43) [1]Как то все запутано объясняешь...
Не может обработчик события Б вызываться во время выполнения обработчика события А (в однопоточном приложении).
Если нужно запретить обработчик введи флаг который будет устанавливаться в одной процедуре и блокировать другую.
← →
Vuk (2003-08-15 21:58) [2]to Романов Р.В.:
>Не может обработчик события Б вызываться во время выполнения
>обработчика события А (в однопоточном приложении).
Очень даже может. Например, Вы пишете присвоение свойству какого-нибудь компонента, а он в ответ на это действие вызывает какой-нибудь OnChange. А насчет флага - все правильно.
← →
Юрий Зотов (2003-08-15 21:58) [3]> SergP © (15.08.03 21:12)
Вообще-то, прав:
Романов Р.В. © (15.08.03 21:43) [1]
Заблокировать можно и без флагов:
procedure TForm1.EventA(...)
begin
SomeComponent.OnEventB := nil;
try
...
finally
SomeComponent.OnEventB := EventB
end
end;
procedure TForm1.EventB(...)
begin
...
end;
Но это не поможет. Потому что причина AV не в этом.
← →
Юрий Зотов (2003-08-15 22:02) [4]Елы-палы... а ведь и правда может.
Но заблокировать все равно можно и без флагов.
← →
Романов Р.В. (2003-08-15 22:12) [5]
> Vuk © (15.08.03 21:58) [2]
Ну да. Перепутал событие с сообщением
← →
SergP (2003-08-15 22:12) [6]
> Романов Р.В. © (15.08.03 21:43) [1]
> Не может обработчик события Б вызываться во время выполнения
> обработчика события А (в однопоточном приложении).
Так я специально повставлял в каждый обработчик нечто типа:
begin
memo1.lines.add("начало обработки события N");
...
...
...
memo1.lines.add("конец обработки события N");
end
И вижу что там полный беспорядок происходит при работе проги:
типа:
начало ...1
начало ...2
конец....2
конец...1
и даже еще хуже бывает.
> SomeComponent.OnEventB := nil;
SomeComponent - это имеется ввиду все компоненты, или нужно конкретный указывать?
> Но это не поможет. Потому что причина AV не в этом.
Возможно. Но это упростит мне отладку...
А вообще какие причины подобных ошибок бывают?
← →
Романов Р.В. (2003-08-15 22:18) [7]Причины простые. Обращение к еще не созданному или уже мертвому объекту
← →
Anatoly Podgoretsky (2003-08-15 22:23) [8]Нельзя, событие это же просто вызов процедуры, если ты ничего не будешь вызывать то и других вызовов обработчиков не будет. А вот лог тебе может помочь, особенное если его сделать по подробнее.
← →
SergP (2003-08-15 22:25) [9]
> Заблокировать можно и без флагов:
Еще вопрос: В твоем примере. Если вызывается event A, при этом блокируются все другие event"ы. Но будут ли они вызываться после завершения A, если компонент "захотел" их сгенерировать в процессе работы A?
← →
Vuk (2003-08-15 22:51) [10]to SergP:
Блокируйте лучше выполнение обработчиков при помощи флагов. Оно так проще. В конце концов может оказаться, что один флаг нужно будет проверять в нескольких обработчиках. Манипулирование одним флагом будет проще, чем переопределение несколько обработчиков.
to Романов Р.В.:
>Ну да. Перепутал событие с сообщением
Что самое интересное, обработчики оконных сообщений теоретически тоже могут сработать во время выполнения другого обработчика. Есть такой метод у TControl - Perform.
← →
Романов Р.В. (2003-08-15 22:57) [11]Vuk
Уболтал, черт языкастый :)
(с) Властелин колец part II
← →
Vuk (2003-08-15 23:01) [12]:o)
← →
SergP (2003-08-15 23:02) [13]
> to SergP:
> Блокируйте лучше выполнение обработчиков при помощи флагов.
> Оно так проще. В конце концов может оказаться, что один
> флаг нужно будет проверять в нескольких обработчиках. Манипулирование
> одним флагом будет проще, чем переопределение несколько
> обработчиков.
так , что-ли?
begin
while flag do Application.ProcessMessage;
flag:=true;
....
flag:=false;
end;
← →
SergP (2003-08-16 03:54) [14]
> так , что-ли?
>
> begin
> while flag do Application.ProcessMessage;
> flag:=true;
>
> ....
>
> flag:=false;
> end;
Но даже если так делать, то ничто не может гарантировать что другой event не сработает когда первый находится между
while flag do Application.ProcessMessage;
и
flag:=true;
Кстати. Если если event срабатывает в процессе работы другого event"a , они оба будут работать в разных потоках, или в одном?
← →
Юрий Зотов (2003-08-16 09:07) [15]> SergP © (16.08.03 03:54) [14]
Если Вы хотите ЗАДЕРЖАТЬ обработку второго события до окончания обработки первого (а не ОТМЕНИТЬ ее), то ProcessMessages не спасет, придется ручками строить стек событий, в нем запоминать порядок их возникновения, а потом их отрабатывать
А если хотите ОТМЕНИТЬ, то все гораздо проще. В Private формы добавьте FInEvent: boolean, а во ВСЕХ обработчиках напишите:
begin
if not FInEvent then
begin
FInEvent := True;
try
... // Код самой обработки
finally
FInEvent := False
end
end
end;
> Если если event срабатывает в процессе работы другого
> event"a , они оба будут работать в разных потоках, или в одном?
У Вас приложение однопоточное? Откуда же возьмется второй поток?
← →
SergP (2003-08-16 10:41) [16]
> У Вас приложение однопоточное? Откуда же возьмется второй
> поток?
Однопоточное. Я дополнительных потоков не создаю.
Но ведь если объект вызывает обработчик, когда работает другой обработчик, то получается что сам объект создает свои потоки для своей работы. Вот и хотел узнать не создает ли он сам дополнительных потоков для своих event"ов....
← →
Юрий Зотов (2003-08-16 11:25) [17]> SergP © (16.08.03 10:41) [16]
> получается что сам объект создает свои потоки для своей
> работы.
Откуда же это получается? Конечно, объект МОЖЕТ это сделать, но вовсе не обязательно. В подавляющем большинстве случаев (если не во всех случаях) объекты Delphi этого и не делают. Потому что иначе может возникнуть проблема. Дело в том, что разработчик объекта никак не может заранее знать, что именно напишет юзер этого объекта в своем обработчике (а написать можно что угодно). Поэтому, если запустить юзерский обработчик в отдельном потоке, то может возникнуть конфликт с однопоточной моделью VCL. Например, если юзер напишет какую-то визуальную обработку, которая должна выполняться в контексте главного потока, а будет выполнена в контексте дополнительного (см. TThread.Synhronize).
Поэтому разработчики объектов так и не делают. Ну разве что "разработчик" совсем уж неграмотный, или объект уж какой-то очень специальный (но тогда должны быть соответствующие оговорки в документации).
> Вот и хотел узнать не создает ли он сам дополнительных потоков
> для своих event"ов....
Вы поймите главное - понятие "событие объекта" в концепции VCL никак с потоками не связано, а с их синхронизацией - тем более. Просто-напросто при определенных условиях объект проверяет, назначен ли в его поле адрес юзерского метода и, если назначен - то вызывает этот метод, в том же самом потоке. Вот вызов этого метода и называется "произошло событие объекта". Вот пример классической (и самой распространенной) схемы события объекта, которое происходит при изменении его свойства:
type
TMyObject = class(...)
private
FMyProp: integer;
FOnMyPropChange: TNotifyEvent;
procedure SetMyProp(const Value: integer);
protected
procedure DoMyPropChange; dynamic;
published
property MyProp: integer
read FMyProp write SetMyProp default 0;
property OnMyPropChange: TNotifyEvent
read FOnMyPropChange write FOnMyPropChange;
end;
procedure TMyObject.SetMyProp(const Value: integer);
begin
if FMyProp <> Value then
begin
FMyProp := Value;
DoMyPropChange // Вызываем метод диспетчеризации
end
end;
procedure TMyObject.DoMyPropChange;
begin
// Проверяем и вызываем юзерский обработчик
if Assigned(FOnMyPropChange) then FOnMyPropChange(Self)
end;
Таким образом, если теперь написать
MyObject.MyProp := 1
то сработает метод SetMyProp и будет вызван обработчик события OnMyPropChange (если юзер его назначил). То есть - как бы произошло событие, а на самом деле просто последовательный вызов методов, один из другого.
Вот и все. Как видите - никаких дополнительных потоков и уж тем более никакой их синхронизации. Это и сеть событие ОБЪЕКТА, а вот Event, как объект синхронизации - это совершенно другая штука, к рассмотренному НИКАК не относящаяся.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.09.01;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.011 c