| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Не могу обработать сообщение WM_USER |
| Автор: Gnus 11.11.2011, 13:40 | ||
| Доброго времени суток. Суть проблемы такова: есть объект, который порождает нить. Нить без освобождения при завершении. Завершение нити может произойти при разрушении родителя, тогда нить тоже разрушается. Но возможны ситуации, когда завершение нити произошло в ходе ее исполнения. Необходимо проинформировать родителя о завершении нити и инициировать его (родителя) разрушение. Попытка решения с помощью сообщений: перед завершением нити вызывается метод родителя, в котором вызывается метод PostMessage(0, WM_USER, 0, 0), которая возвращает истину. У родителя описан следующий метод обработки сообщения WM_USER:
в реализации WMUser пока что только контрольная печать в файл. Вобщем, не вызывается этот WMUser. Уже и не знаю, что делать. |
| Автор: kami 11.11.2011, 20:44 |
Первый параметр функции, конечно, просто так придуман... Это намек. Остальное скажут F1 и MSDN |
| Автор: kami 12.11.2011, 09:40 |
Попробовал бы он запретить Только не надо забывать про Метод, содержащий PostMessage, вызывается в контексте порожденной нити (судя по описанию). То, что этот метод содержится не в самом коде потока, а в коде родителя. ничего не меняет. Куда отправится сообщение? Ждут ли его там, куда оно в действительности улетело? |
| Автор: Gnus 12.11.2011, 09:47 | ||
но разве эта процедура в коде родителя не является обработчиком события? Попробовал перекрыть DefaultHandler родителя - не выполняется. Событие OnTerminate у потока тоже не выполняется. Какой-то замкнутый круг. Повторюсь: Родитель (наследник TObject) порождает нить (наследник TThread). При завершении нити необходимо разрушить родителя. Что посоветуете? |
| Автор: kami 12.11.2011, 11:33 |
| Еще раз повторяю: PostMessage будет вызвано в контексте созданного потока. Это значит, что сообщение (при параметре Handle = 0) будет отправлено именно этому созданному потоку. А там оно не нужно. Потому что в этом случае сообщение нужно отправлять не потоку, а требуемому окну. И скорее всего у этого потока даже выборка сообщений не реализована. Я не знаю, что это за компонент-родитель. Может, и не является, если родитель - не оконный. В любом случае, сообщение до него не доходит. |
| Автор: Gnus 12.11.2011, 11:48 |
| Т.е., насколько я понял, использовать механизм сообщений нельзя. Никакого "требуемого окна" у меня нет. Как же организовать отложенное уведомление родителя о завершении потока? |
| Автор: kami 12.11.2011, 11:55 |
Я этого не говорил. Если нет - не проблема создать. Что представляет из себя родитель? Что за класс (если собственный - наследник какого базового)? |
| Автор: Gnus 12.11.2011, 12:02 | ||||
|
| Автор: kami 12.11.2011, 12:41 | ||||
Это не страшно. Принцип работы следующий (код будет отрывками, только концепция, возможно несколько ошибок, т.к. пишу прямо в браузере): 1. Объявляем приватную переменную myHandle:THandle и оконную процедуру myMsgHandler(var Message: TMessage) 2. В конструкторе объекта (надеюсь, этот объект создается в главном потоке?) пишем:
3. Создаваемому потоку передаем этот myHandle. Где он будет храниться - определите сами. 4. в процедуре myMsgHandler пишем следующее:
5. При необходимости передачи сообщения в методе вторичного потока пишем PostMessage(ParentHandle, WM_User.....). И не нужно вызывать методы родителя, прямо в коде вторичного потока, он же из п.2 знает хендл нужного окна. Добавлено через 1 минуту и 57 секунд Обратите внимание на В противном случае манипуляции могут резко поменяться или дополниться. |
| Автор: Gnus 12.11.2011, 13:30 |
| kami, огромное спасибо. Признаюсь, не знал, что можно привязать к обычному объекту окно с функцией обработки сообщений. До сегодняшнего дня не задумывался о том, как работает тот же TTimer например. Так что еще раз спасибо за AllocateHWND. Кстати, в деструкторе родителя приходится делать DeallocateHWND. Если под главным потоком Вы имели ввиду поток VCL, то тогда ответ отрицательный. Объект-родитель создается другими объектами при вызове главным потоком функции подключения из dll. Соответственно, в списке потоков я вижу их один после запуска приложения, три после вызова функции подключения из dll. После неудачи подключения теперь остается только один поток, как я и хотел. |
| Автор: kami 12.11.2011, 14:02 | ||
Я рад, что Вы не ограничились только воспроизведением моего совета.
Это (дальше - 2 варианта): а) ничего не значит, потому что несмотря на создание других потоков, объект создается в контексте основного (да, я говорил именно проVCL-поток). В этом случае всё отлично, потому что vcl поток имеет обработчик сообщений. б) если объект создается в дополнительном потоке и всё работает, значит этот дополнительный поток создал и имеет очередь сообщений, ну и обрабатывает их, само собой. Если бы поток не имел цикл обработки сообщений, то ни одно окно, созданное в его контексте (в т.ч. и созданное AllocateHWND) ничего бы не получало. |