घर
Top.Mail.Ru Yandeks.Metrika
मंच: "मुख्य";
वर्तमान संग्रह: 2003.09.01;
डाउनलोड करें: [xml.tar.bz2];

नीचे

किसी अन्य घटना के पूरा होने तक भी टा कॉल पर रोक लगाना संभव है इसी तरह की शाखाएँ खोजें


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(...)
शुरू करना
SomeComponent.OnEventB := nil;
कोशिश
...
आखिरकार
SomeComponent.OnEventB := EventB
समाप्त
अंत;

procedure TForm1.EventB(...)
शुरू करना
...
अंत;

Но это не поможет. Потому что причина AV не в этом.



Юрий Зотов   (2003-08-15 22:02) [4]

Елы-палы... а ведь и правда может.
Но заблокировать все равно можно и без флагов.



Романов Р.В.   (2003-08-15 22:12) [5]


> वुक © (15.08.03 21: 58) [2]

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



SergP   (2003-08-15 22:12) [6]


> रोमानोव आर.वी. © (15.08.03 21: 43) [1]
> Не может обработчик события Б вызываться во время выполнения
> обработчика события А (в однопоточном приложении).


Так я специально повставлял в каждый обработчик нечто типа:

शुरू करना
memo1.lines.add("начало обработки события N");
...
...
...
memo1.lines.add("конец обработки события N");
समाप्त

И вижу что там полный беспорядок происходит при работе проги:
प्रकार:
начало ...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]

वुक
Уболтал, черт языкастый :)
(с) Властелин колец part II



Vuk   (2003-08-15 23:01) [12]

: ओ)



SergP   (2003-08-15 23:02) [13]


> to SergP:
> Блокируйте лучше выполнение обработчиков при помощи флагов.
> Оно так проще. В конце концов может оказаться, что один
> флаг нужно будет проверять в нескольких обработчиках. Манипулирование
> одним флагом будет проще, чем переопределение несколько
> обработчиков.


так , что-ли?

शुरू करना
while flag do Application.ProcessMessage;
ध्वज: = सत्य;

....

ध्वज: = असत्य;
अंत;



SergP   (2003-08-16 03:54) [14]


> так , что-ли?
>
> शुरू करो
> while flag do Application.ProcessMessage;
> flag:=true;
>
> ....
>
> flag:=false;
> अंत;


Но даже если так делать, то ничто не может гарантировать что другой event не сработает когда первый находится между
while flag do Application.ProcessMessage;
и
ध्वज: = सत्य;

Кстати. Если если event срабатывает в процессе работы другого event"a , они оба будут работать в разных потоках, или в одном?



Юрий Зотов   (2003-08-16 09:07) [15]

> SergP © (16.08.03 03:54) [14]

Если Вы хотите ЗАДЕРЖАТЬ обработку второго события до окончания обработки первого (а не ОТМЕНИТЬ ее), то ProcessMessages не спасет, придется ручками строить стек событий, в нем запоминать порядок их возникновения, а потом их отрабатывать

А если хотите ОТМЕНИТЬ, то все гораздо проще. В Private формы добавьте FInEvent: boolean, а во ВСЕХ обработчиках напишите:

शुरू करना
if not FInEvent then
शुरू करना
FInEvent := True;
कोशिश
... // Код самой обработки
आखिरकार
FInEvent := False
समाप्त
समाप्त
अंत;

> Если если 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 никак с потоками не связано, а с их синхронизацией - тем более. Просто-напросто при определенных условиях объект проверяет, назначен ли в его поле адрес юзерского метода и, если назначен - то вызывает этот метод, в том же самом потоке. Вот вызов этого метода и называется "произошло событие объекта". Вот пример классической (и самой распространенной) схемы события объекта, которое происходит при изменении его свойства:

टाइप
TMyObject = class(...)
निजी
FMyProp: integer;
FOnMyPropChange: TNotifyEvent;
procedure SetMyProp(const Value: integer);
संरक्षित
procedure DoMyPropChange; dynamic;
प्रकाशित
property MyProp: integer
read FMyProp write SetMyProp default 0;
property OnMyPropChange: TNotifyEvent
read FOnMyPropChange write FOnMyPropChange;
अंत;

procedure TMyObject.SetMyProp(const Value: integer);
शुरू करना
if FMyProp <> Value then
शुरू करना
FMyProp := Value;
DoMyPropChange // Вызываем метод диспетчеризации
समाप्त
अंत;

procedure TMyObject.DoMyPropChange;
शुरू करना
// Проверяем и вызываем юзерский обработчик
if Assigned(FOnMyPropChange) then FOnMyPropChange(Self)
अंत;

Таким образом, если теперь написать
MyObject.MyProp := 1
то сработает метод SetMyProp и будет вызван обработчик события OnMyPropChange (если юзер его назначил). То есть - как бы произошло событие, а на самом деле просто последовательный вызов методов, один из другого.

Вот и все. Как видите - никаких дополнительных потоков и уж тем более никакой их синхронизации. Это и сеть событие ОБЪЕКТА, а вот Event, как объект синхронизации - это совершенно другая штука, к рассмотренному НИКАК не относящаяся.



पन्ने: 1 पूरी शाखा

मंच: "मुख्य";
वर्तमान संग्रह: 2003.09.01;
डाउनलोड करें: [xml.tar.bz2];

ऊपर





मेमोरी: 0.63 एमबी
समय: 0.053 c
1-1390
imp403
2003-08-16 12:57
2003.09.01
64x आइकन


1-1385
IgoX
2003-08-19 14:45
2003.09.01
एक्सएमएल


14-1654
Layner
2003-08-12 13:06
2003.09.01
आपने क्या किया है, निक्की के विशेषज्ञों के लिए ऑफ़लाइन मंच


14-1672
Marser
2003-08-12 02:07
2003.09.01
और मैं नरम क्यों नहीं हूं?


14-1630
ई मेरा नाम
2003-08-13 09:52
2003.09.01
पागलपन मजबूत था





अफ्रीकी अल्बानियन अरबी भाषा अर्मेनियाई आज़रबाइजानी बस्क बेलारूसी बल्गेरियाई कैटलन सरलीकृत चीनी) चीनी पारंपरिक) क्रोएशियाई चेक डेनिश डच अंग्रेज़ी एस्तोनियावासी फिलिपिनो फिनिश फ्रेंच
गैलिशियन् जॉर्जियाई जर्मन यूनानी हाईटियन यहूदी हिंदी हंगरी आइसलैंड का इन्डोनेशियाई आयरिश इतालवी जापानी कोरियाई लात्वीयावासी लिथुआनियाई मेसीडोनियन मलायी मोलतिज़ नार्वेजियन
फ़ारसी पोलिश पुर्तगाली रोमानियाई रूसी सर्बियाई स्लोवाक स्लोवेनियाई स्पेनिश स्वाहिली स्वीडिश थाई तुर्की यूक्रेनी उर्दू वियतनामी वेल्श यहूदी बंगाली बोस्नियाई
सिबुआनो एस्पेरांतो गुजराती हौसा हमोंग ईग्बो जावानीस कन्नड़ खमेर लाओ लैटिन माओरी मराठी मंगोलियन नेपाली पंजाबी सोमाली तामिल तेलुगु योरूबा
ज़ुलु
Английский Французский Немецкий Итальянский Португальский Русский Испанский