Здоровеньки булы, Олл
Интересует технология работы с событиями, в частнгости такие моменты:
— кто вызывает метод-обработчик: объект, генерирующий событие, или поток, в контексте которого создан объект?
— какая разница в поведениее системы при генерировании события в объекте, созданном в стандартной нити (thread) и во вторичной?
Это пока все. Если нужно для ответа, объясню зачем это мне.
Приветствуются аргументированные имхи и литература.
Спасибо.
Здравствуйте, Eeereal, Вы писали:
E>Интересует технология работы с событиями, в частнгости такие моменты:
E> — кто вызывает метод-обработчик: объект, генерирующий событие, или поток, в контексте которого создан объект?
Скажем, TControl получает компонентные сообщения, например, cm_activate.
Эти сообщения, в большинстве, дублируют сообщения Windows, тот же
WM_ACTIVATE, но, т.к. не все TControl имеют окно (не TWinControl),
они могут пересылаться и не через Post/SendMessage.
Обработчик сообщения cm_activate
type
TXControl = class(TControl)
..
private
{ Private declarations }
procedure CMActivate(var Message: TCMActivate); message cm_activate;
..
end;
вызывает метод диспетчеризации (procedure Activate; dynamic) который
проверяет наличие обработчика OnActivate и вызывает его с
требуемыми параметрами (Self).
Но обработчики не обязательно представляют реакцию на сообщение:
http://groups.google.com/groups?selm=4083167687%40f1003.n5080.z2.fidonet.ftn
Кроме того, ясно, что объект, генерирующий событие (например, посланием
сообщения), может быть в другом потоке (в другом приложении, в системе).
E> — какая разница в поведениее системы при генерировании события в объекте, созданном в стандартной нити (thread) и во вторичной?
Т.к. VCL в основном непотокобезопасна, то обработку событий проще всего делать
в контексте первичного потока (в случае участия визуальных компонентов).
Для этого, например, предназначен Synchronize
E>Это пока все. Если нужно для ответа, объясню зачем это мне.
Конечно, дополнительная информация не мешает.
Даже сам термин "событие" неоднозначен.
Здравствуйте, Eeereal, Вы писали:
E>Здоровеньки булы, Олл
E>Интересует технология работы с событиями, в частнгости такие моменты:
E> — кто вызывает метод-обработчик: объект, генерирующий событие, или поток, в контексте которого создан объект?
Объект, генерирующий событие, вызывает обработчик события по указателю, переданному в объект. Обработчик события будет выполнен в контексте вызывающего потока.
E> — какая разница в поведениее системы при генерировании события в объекте, созданном в стандартной нити (thread) и во вторичной?
Никакой. Обработчик события всегда будет вызван в контексте вызывающего потока (сорри, но по другому не скажешь). Другое дело, что если вы из вторичного потока захочите повзаимодействовать с GUI-потоком VCL (который суть всегда первичный) — то все, приехали. Либо — Synchronyze (с случае, если ваш класс потока производный от TThread), либо исключительно через SendMessage в нужное окно, принадлежащее первичному потоку.
В остальном пользуйтесь событиями как угодно. Помните лишь об одном — если вы в обработчике события хотите обратиться к объектам VCL — это обращение должно выполняться в контексте главного потока приложения. Ну вот так вот VCL спроектирована
Здравствуйте, Flamer, Вы писали:
F> Ну вот так вот VCL спроектирована
Хм. Вопрос (не провокация, а именно — не знаю) — есть ли библиотеки сравнимого качества, спроектированные иначе и работающие с нормальной скоростью и надежностью?
Лично я, познакомившись с jdk, стал еще больше ценить VCL
P.S. Под нормальной надежностью я имею в виду, что я как пользователь не могу добиться долгой блокировки естественными вызовами этой библиотеки.
Здравствуйте, Leonid Troyanovsky, Вы писали:
LT> Конечно, дополнительная информация не мешает.
LT> Даже сам термин "событие" неоднозначен.
Ситуация следующая:
В динамически подгружаемой библиотеке выполняются операции через TADOConnection.Execute(...).
ConnectionString для операции передается извне, и сам объект-соединение создается уже в библиотеке.
Событию OnExecuteComplete назначается метод объекта, созданного в этой же библиотеке.
При выполнении такого кода все происходит обычно: выполнил-событие о завершении-обработчик-следующая строка кода.
Connection.Execute(Script, cmdText, Sync) // Sync=[], выполнение обычное, без изысков
Если выполнять этот метод в асинхронном режиме
Connection.Execute(Script, cmdText, Sync) // Sync=[eoAsyncExecute], выполняем асинхронно
OnExecFinished.WaitFor(INFINITE); // OnExecFinished : TEvent
Событие OnExecFinished устанавливается (TEvent.SetEvent) в обработчике события TADOConnection.OnExecuteComplete.
Если выполнять этот код с объектом Connection, созданном в контексте главного потока (при инициализации библиотеки), то события возникают и обрабатываются, как я и хочу.
Если Connection создан в контексте вторичного потока, то событие возникает, но не обрабатывается.
Это, на самом деле, наверное, нормально

.
При такой работе, в поток, в котором создано подключение, приходят некие сообщения, которых он не получает, если выполняются операции в Conection, созданном в главном потоке.
Очевидно, что сообщения о происшедших событиях объект отсылает создавшему его потоку.
В главном потоке эти сообщения корректно обрабатываются.
В моем же вторичном потоке я их никак не обрабатываю, просто потому что не знаю, как по пришедшему сообщению выяснить для какого объекта возникло событие.
При этом не совсем ясно, почему проблема возникает только при асинхронном выполнении операции в Execute.