Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.04.01;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.038 c
3-1168578488
O.O
2007-01-12 08:08
2007.04.01
Аналоги Round и Trunc в FireBird


4-1163501617
novill
2006-11-14 13:53
2007.04.01
Как программно нажать (Num,Caps,Scroll)Lock?


9-1145118671
Sulim
2006-04-15 20:31
2007.04.01
Шуйдеры


4-1163427605
OMGovdan
2006-11-13 17:20
2007.04.01
Переименование файлов по маске


2-1173630858
Игорек
2007-03-11 19:34
2007.04.01
Windows API





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский