Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.04.01;
Скачать: CL | DM;

Вниз

Объясните   Найти похожие ветки 

 
Sam Stone ©   (2007-03-07 07:53) [0]

Доброго времени суток. Как работать с GetMessage и PostThreadMessage? Хочется покидаться сообщениями в поток (в общеобразовательных целях). Делаю так (по примерам с мсдн и гугля):
function f1(p:pointer):dword;
var m:TMsg;
begin
 PeekMessage(m,0,wm_user,wm_user,pm_noremove);//из дельфёвого хелпа
 while GetMessage(m,0,0,0) do begin //или integer(GetMessage())>0
   if m.message=SomeWalue then BlaBlaBla;
   TranslateMessage(m);
   DispatchMessage(m);
 end;
end;
...
//запускаем поток
CloseHandle(BeginThread(nil,0,@f1,nil,0,ThreadIDVar));
...
//сообщение, например, по нажатию на кнопку
PostThreadMEssage(ThreadIDVar,wm_user+1,0,0);

При вызове GetMessage поток тихо помирает, т.е. в дебаге дальше не идет, по Ф8 программа запускается. С PeekMessage то же самое, разве что если использовать PM_NOREMOVE флаг и сперва в потоке запостить любое сообщение, то все будет крутиться, но другие мессаги я поймать не смог.
Понять в чем в данном случае проблема за неимением опыта не получается, поэтому прошу направить на путь истинный :)


 
Сергей М. ©   (2007-03-07 08:17) [1]

function MyThreadFunc(p:pointer):dword;
var
 m:TMsg;
begin
while GetMessage(m,0,0,0) do
  case m.Message of
   WM_USER+1: BlaBlaBla;
  else
    TranslateMessage(m);
    DispatchMessage(m);
  end;
end;

...
CloseHandle(BeginThread(nil,0,@f1,nil,0,ThreadIDVar));
while not PostThreadMEssage(ThreadIDVar,wm_user+1,0,0) do;

..
//по получению этого сообщения потчная функция завершит свою работу
PostThreadMEssage(ThreadIDVar, WM_QUIT,0,0);


 
Sam Stone ©   (2007-03-07 08:46) [2]

Спасибо. А с чем связано
> while not PostThreadMEssage(ThreadIDVar,wm_user+1,0,0) do;

?
долбить пока не будет создана очередь?


 
Сергей М. ©   (2007-03-07 09:20) [3]


> Sam Stone ©   (07.03.07 08:46) [2]


> долбить пока не будет создана очередь?


Да.

Если очередь не создана, то сообщение будет послано "в пустоту", о чем и скажат False-результат вызова PostThreadMEssage().

А очередь будет создана при первом вызове WaitMessage/GetMessage/PeekMessage


 
Sam Stone ©   (2007-03-07 09:41) [4]

а с чем тогда связана смерть потока на GetMessage, если убрать while not PostThreadMessage? Не могу понять... Пост уходит в никуда, т.к. нет очереди, а очередь создается через гет/пик...


 
Сергей М. ©   (2007-03-07 11:06) [5]

"Смерть" потока связана с посылкой ему сообщения WM_QUIT.

GetMessage() создает очередь (если она еще не создана) и выбирает из ее головы сообщения (если очередь пуста, ф-ция блокирует выполнение потока до момента появления в очереди хотя бы одного сообщения).

WM_QUIT является специальным предопределенным сообщением, при выборке которого ф-ция возвращает False (для любых иных выбранных сообщений ф-ция возвращает True). Как только ф-ция вернет False, WHILE-цикл, в котором она вызывается, прерывает свою работу.


 
Sam Stone ©   (2007-03-07 11:36) [6]

Нет, я не про то... Если убрать while not PostThreadMessage при выполнении GetMessage поток тихо умрет. try except не помогает, посмотреть результат через variable:=GetMessage() тоже не получается. Цикл даже не отрабатывается ни разу.
Когда делал так

function f1(p:pointer):dword;
...
begin
PostThreadMessage(GetCurrentThreadID,wm_user,0,0);
while GetMessage(m,0,0,0) do begin

end;

то первый раз цикл отрабатывался, получая сообщение wm_user, а на следующей итерации поток умирал. При этом не удалось установить, что возвращает GetMessage. Даже watch подвис :). Такое ощущение, что при пустой очереди происходит эксепшн.

В качестве полноценного примера:

function f2(p:pointer):dword;
 var m:TMsg;
 lb:longbool;
begin
 lb:=GetMessage(n,0,0,0);
 sleep(0);//если поставить брякпоинт - никогда не сработает из-за вылета на GetMessage
end;
...
BeginThread(nil,0,@f2,nil,ThreadID);


 
Сергей М. ©   (2007-03-07 11:51) [7]


> Sam Stone ©   (07.03.07 11:36) [6]


Мне не совсем понятна цель твоих экспериментов.
Ты бы описал конкретно поставленную задачу ...

Ну, например, создать доп.поток, который должен реагировать на такие-то адресованные ему извне сообщения таким-то конкретным образом....

В моем примере созданный поток явно реагирует на сообщение WM_USER+1 запуском процедуры BlaBlaBla, все прочие сообщения (кроме WM_QUIT) диспетчеризует по-умолчанию, при получении WM_QUIT немедленно завершает работу.

?


 
Leonid Troyanovsky ©   (2007-03-07 12:00) [8]


> Sam Stone ©   (07.03.07 11:36) [6]

> В качестве полноценного примера:

> function f2(p:pointer):dword;
>  var m:TMsg;
>  lb:longbool;
> begin
>  lb:=GetMessage(n,0,0,0);
>  sleep(0);//если поставить брякпоинт - никогда не сработает
> из-за вылета на GetMessage
> end;
> ...
> BeginThread(nil,0,@f2,nil,ThreadID);


У тебя пропущен stdcall, поэтому все и умирает.

Потоку создается очередь при вызове им _любой_ user32
функциии: хоть GetMessage, хоть PostMessage.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-03-07 12:03) [9]


> Leonid Troyanovsky ©   (07.03.07 12:00) [8]

> У тебя пропущен stdcall, поэтому все и умирает.

Sorry, не заметил, что beginthread.

Но, в любом случае, причины смерти не в отсутствии очереди.

--
Regards, LVT.


 
Сергей М. ©   (2007-03-07 12:08) [10]


> первый раз цикл отрабатывался, получая сообщение wm_user,
>  а на следующей итерации поток умирал


Он не "умирал", он был блокирован на очередном выполнении GetMessage за отсутствием каких-либо сообщений в очереди. Единственное посланное wm_user-сообщение было выбрано при первой итерации, а больше в очереди ничего нет


 
Sam Stone ©   (2007-03-07 12:11) [11]


> Ты бы описал конкретно поставленную задачу ...

собсна вот она

> создать доп.поток, который должен реагировать на такие-то
> адресованные ему извне сообщения таким-то конкретным образом

НО! Если в коде

> CloseHandle(BeginThread(nil,0,@f1,nil,0,ThreadIDVar));
> while not PostThreadMEssage(ThreadIDVar,wm_user+1,0,0) do;

убрать while то произойдет непонятная ошибка в потоке при вызове GetMessage, после которой он (поток) прекратит свое выполнение. Меня интересует, почему такое происходит? Т.е. почему без while not PostThreadMEssage(ThreadIDVar,wm_user+1,0,0) do; код не работает (баг/косяк/кривые руки)?

[1] меня полностью удовлетворяет, я рад и кидаюсь сообщениями :) Но мне хочется понять суть вышеописанной ошибки.
Вроде бы все понятно описал.


 
Sam Stone ©   (2007-03-07 12:14) [12]


> Сергей М. ©   (07.03.07 12:08) [10]

кажется дошло ) т.е. это он так засыпает оригинально?


 
Сергей М. ©   (2007-03-07 12:31) [13]


> это он так засыпает оригинально?


Он не засыпает, он ждет сообщения.

То сообщение wm_user+1, что ты послал однократно (т.е. без while-цикла), ушло "в пустоту", потому что в момент отправки очередь еще не существовала (она начнет существование только при первом вызове GetMessage в потоке-адресате).

Иными словами, цикл while not PostThreadMessage() гарантирует ожидание создания целевой очереди и достоверное помещение в эту очередь сообщения. Без этого цикла такой гарантии нет.


 
Sam Stone ©   (2007-03-07 12:43) [14]

Теперь мне всё понятно ) спасибо :)


 
Сергей М. ©   (2007-03-07 12:50) [15]


> Sam Stone ©   (07.03.07 12:43) [14]


Разберись еще в назначении ф-ций TranslateMessage/DispatchMessage и действительной необходимости их вызова в твоем случае (а в твоем случае из вызов избыточен) - вот тогда будет полное понимание.



Страницы: 1 вся ветка

Текущий архив: 2007.04.01;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.056 c
15-1173236991
Slider007
2007-03-07 06:09
2007.04.01
С днем рождения ! 7 марта


1-1170926314
kilop
2007-02-08 12:18
2007.04.01
как сделать так чтобы при запуске форма появлялась в центре


15-1172928103
Sergius P
2007-03-03 16:21
2007.04.01
Подсчет трафика


1-1171005992
Choco
2007-02-09 10:26
2007.04.01
AutoSize для компонента Animate


4-1163515236
Max_2006
2006-11-14 17:40
2007.04.01
Вывести bmp-рисунок на окно на API