Форум: "Начинающим";
Текущий архив: 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.05 c