Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.5 MB
Время: 0.018 c
1-93431
oleg
2004-01-15 09:55
2004.01.29
JavaScript и Delphi


14-93646
Undert
2004-01-09 10:49
2004.01.29
PHP + MySQL


3-93390
pashtet
2003-12-30 14:13
2004.01.29
TtreeView


4-93733
frost
2003-11-02 20:12
2004.01.29
---|Ветка была без названия|---


6-93621
h0use
2003-11-24 15:32
2004.01.29
Непонятная проблема с буфером в Инди компоненте