Текущий архив: 2004.01.29;
Скачать: CL | DM;
ВнизРабота с потоками в Delphi с использованием VCL Найти похожие ветки
← →
YuRock (2004-01-15 14:18) [0]Уважаемые мастера!
Как вы знаете, в Delphi Help"е четко написано: "methods that access a VCL object and update a form must only be called from within the main VCL thread" - т.е. обращаться к объктам VCL (т.е. окнам и т.д.) можно только в главном потоке.
Я же, решив проверить это утверждение, получил следующий результат: на самом деле с объектами работать можно, но как только идет обращени к непосредственно оконному свойству - поток зависает...
Происходит это потому, что зависает ф-ция SendMessage, которая отправляет соответствующее сообщение окну.
Так как мне необходимо было обойти эту проблему, я нашел 2 выхода:
1. Отправлять сообщение окну через PostMessage, а по этому сообщению выполнять какие нужно операции с окном. Этот метод будет работать в главном потоке - по-этому все в порядке.
2. Отказаться от использования VCL. В файле проекта убрать инициализацию Application и цикл обработки сообщений написать вручную:
while GetMessage(msg, 0, 0, 0) do begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
Оба этих метода каждый по-своему плохи. Так как и VCL я люблю, и SendMessage из другого потока иногда необходимо выполнять.
Вопрос: почему (конкретно) не получается выполнить SendMessage и как (если возможно) эту проблему обойти?
← →
Polevi (2004-01-15 14:20) [1]TThread.Synchronize
← →
Digitman (2004-01-15 14:23) [2]
> Происходит это потому, что зависает ф-ция SendMessage, которая
> отправляет соответствующее сообщение окну.
а ты выяснил конкретные причины "зависания", прежде чем делать какие-то умозаключения ?
← →
YuRock (2004-01-15 14:31) [3]> Polevi © (15.01.04 14:20) [1]
> TThread.Synchronize
Это не выход (я даже писать об этом не стал). Какой смысл делать поток, если написать в нем Synchronize? Нет, иногда можно, но чаще всего прийдется все операции туда засовывать, а это идиотизм, извините.
> Digitman © (15.01.04 14:23) [2]
> а ты выяснил конкретные причины "зависания", прежде чем делать какие-то умозаключения ?
Вот об этих "конкретных" причинах я и хотел у Вас (и не только у Вас) спросить, т.к. виснет любой SendMessage!
← →
Digitman (2004-01-15 14:41) [4]
> Это не выход (я даже писать об этом не стал). Какой смысл
> делать поток, если написать в нем Synchronize?
смысл как раз прямой : если требуется синхронизация некоего вызова метода с осн.код.потоком, то сей метод как раз для этого и предназначен... в D5 метод Synchronize() внутри себя как раз и выполняет Sendmessage(), в последующих версиях - несколько иначе, но с той же сутью
> виснет любой SendMessage
очевидно, потому что поток-приемник сообщения в этот момент занят некоей длительной операцией, в течение которой не происходит выборка и обработка посылаемого ему сообщения ... Sendmesssage() в случае межпоточного вызова будет ждать, пока поток-приемник не сподобится выбрать это сообщение из очереди и не обработает его (т.е. пока оконная ф-ция целевого окна не будет полностью выполнена)
← →
YuRock (2004-01-15 14:54) [5]> Digitman © (15.01.04 14:41) [4]
> смысл как раз прямой : если требуется синхронизация некоего вызова метода с осн.код.потоком
Да, но не ради любого же SendMessage Synchronize вызывать?!! Это же тормоз страшный!
> Digitman © (15.01.04 14:41) [4]
> очевидно, потому что поток-приемник сообщения в этот момент занят некоей длительной операцией
Нет. Дело не в этом. Если б причины были в этом, я б вопрос не задавал. Если хотите - можете сами попробовать. Если Application.Run не использовать - ничего не зависает. Вот где-то там и проблема, но в чем конкретно?..
← →
Digitman (2004-01-15 15:01) [6]
> Да, но не ради любого же SendMessage Synchronize вызывать?!!
> Это же тормоз страшный!
Synchronize() предназначен для иного, хотя и использует в своей реализации Sendmessage()
А "тормоза" - это, скорей всего, признак неумелого или неуместного использования метода
приводи сюда код. посмотрим, что там к чему у тебя ... может, ты просто с параметрами наблудил что-то ...
← →
YuRock (2004-01-15 15:44) [7]> приводи сюда код. посмотрим, что там к чему у тебя
И глубоко извиняюсь, но, к сожалению, я сейчас не могу повторить этой ситуации. Как только смогу - немедленно приведу код.
← →
Digitman (2004-01-15 15:50) [8]
> YuRock © (15.01.04 15:44) [7]
как вам будет угодно, сударь)
думаю, это прежде всего - в Ваших интересах
← →
panov (2004-01-15 16:28) [9]>YuRock © (15.01.04 14:18)
"methods that access a VCL object and update a form must only be called from within the main VCL thread"
либо использовать различные методы синхронизации при работе различных потоков, например, критические секции -
TCriticalSection - VCL
InitializeCriticalSection/EnterCriticalSection/LeaveCriticalSection/DeleteCriticalSection
← →
YuRock (2004-01-15 16:30) [10]Уважаемые мастера! Я повторил ситуацию, но уже сам понял, в чем была проблема (во мне :))).
Дело в том, что в главном потоке стоял WaitForSingleObject, который ждал, пока мой поток даст сигнал (SetEvent).
Т.е. главный поток временно висел, а мой поток повис, пока главный не обработает SendMessage, но так как он тоже висит - ...
В общем, всем спасибо. С вопросом разобрался (благодаря Digitman - при попытке повторить ситуацию и показать пример кода).
← →
YuRock (2004-01-15 16:47) [11]Так что продолжаем любить VCL!
Страницы: 1 вся ветка
Текущий архив: 2004.01.29;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.008 c