Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Будет ли форма получать и обрабатывать сообщения при ожидании? [D7, WinXP]


Страницы:   1 2

Aleksandr. ©   (2004-09-21 16:08:00) 

В методе окна запускается поток, и окно ждет его завершения через WaitForSingleObject в цикле. Но этот поток может через PostMessage отправлять сообщения этому окну. Вот я и запутался совсем - будет ли оно в этом состоянии получать и обрабатывать эти сообшения? И как вообще правильнее это организовать, если такой подход неприемлем?


KSergey   (2004-09-22 11:42:00) [21]

Скорее всего вместо вот этого

> MsgWaitForMultipleObjects(2,F,false,1000,QS_PostMessage)

Надо написать

MsgWaitForMultipleObjects(2,F[0],false,1000,QS_PostMessage)

А вообще сам сейчас страдаю... Хотя бы для тек. процесса... И нифига.. Первый раз проходит сразу (ну ладно, возможно сообщения есть), а на второй - "неверный дескриптор"...

Делаю так:

 var
   rrr: DWORD;
   pH: THandle;
 begin
   pH := GetCurrentThread;  
........
         while .... do
         begin
           rrr := MsgWaitForMultipleObjects(1, pH, FALSE, INFINITE, QS_ALLINPUT);
           if rrr = WAIT_FAILED then  RaiseLastWin32Error;
           ...
         end;


И нифига... (в смысле вышеуказанная бяка).
Если вместо GetCurrentThread поставить GetCurrentProcess - никогда в MsgWaitForMultipleObjects не задерживается...


Aleksandr.   (2004-09-21 17:33:00) [22]

Нифига не пойму. Сделал для теста:

type
 TTestThread = class (TThread)
   Event : HWND;
   FormH : Hwnd;
   constructor Create(aEv,aH : HWND);
   procedure Execute; override;
 end;

procedure TForm1.Button8Click(Sender: TObject);
var
 T : TTestThread;
 A : HWND;
 D : cardinal;
begin
 A:=CreateEvent(nil,true,false,nil);
 T:=TestThread.Create(A,Handle);
 T.Resume;
 repeat
   D:=MsgWaitForMultipleObjects(1,A,false,1000,QS_AllINPUT)
 until D=Wait_Object_0+1;
 T.Terminate;
 T.Free;
 CloseHandle(A)
end;

constructor TestThread.Create;
begin
 Inherited Create(true);
 FormH:=aH;
 Event:=aEv
end;

procedure TestThread.Execute;
var
 i : integer;
begin
 for i:=0 to 4 do begin
   Sleep(500);
   PostMessage(FormH,um_1,0,0)
 end;
 SetEvent(Event)
end;

procedure TForm1.DoMsg(var Message: TMessage); {message UM_1}
begin
 LB.Items.Add('!')
end;

и сразу же срабатывает D=Wait_Object_0+1. А если ставлю маску QS_PostMessage - разница только в том, что уже после выхода из цикла форма вставляет в листбокс все полученные "!".
А если пытаюсь так:

var
..
 F : array [0..1] of hwnd;
begin
 A:=CreateEvent(nil,true,false,nil);
 T:=TestThread.Create(A,Handle);
 F[0]:=A;
 F[1]:=UM_1;
 T.Resume;
 repeat
   D:=MsgWaitForMultipleObjects(2,F,false,1000,QS_PostMessage)
 until D=Wait_Object_0+1;

то вообще все умирает :(


Digitman   (2004-09-21 17:03:00) [23]


> или он будет просыпаться от любых сообщений?


именно !


Aleksandr.   (2004-09-21 17:00:00) [24]

Опять не понял. Так в массив хэндлов ему нужно указывать, какие сообщения должны его пробуждать или он будет просыпаться от любых сообщений? И что должно быть в параметре fWaitAll? Мне же не нужно, чтобы он посчитал результат =Wait_Object_0, если не было установлено событие.


Digitman   (2004-09-21 16:49:00) [25]

да, MsgWaitFor-вызов вернет управление ЛИБО при срабатывании указанного объекта синхр-ции ЛИБО при непустой очереди сообщений


Aleksandr.   (2004-09-21 16:39:00) [26]

Digitman © :
Ой, а можно подробнее? Я по Вашей подсказке нашел MsgWaitForMultipleObjects, только не совсем понял, как он работает. Насколько я понял, ему в хэндлы загоняется созданный эвент и сообщения, которые будут посылаться из ожидаемого потока, а в маску QS_POSTMESSAGE, и тогда, помимо выхода из ожидания по SetEvent, он будет также выходить и как только придет какое-то из упомянутых сообщений?


Digitman   (2004-09-21 16:21:00) [27]


> Надо же, чтобы приложение не выглядило повисшим


а это означает, что осн.трэд, желающий того, должен в таких "узких местах" пользовать MsgWaitFor.. вместо WaitFor..


Aleksandr.   (2004-09-21 16:21:00) [28]

clickmaker ©  :
Кстати, по поводу ProcessMessages. Есть жестокая вещь с ним у меня - вызов его в окне, получающем сообщения от потока, приводит к моментальному выпадению программы. А из Делфи - к дебагу ЦПУ. Проще говоря, сначала я пытался сделать так


...
FUpdator.Resume;
repeat
 Application.ProcessMessages
until FUpdator.Terminated;

Вот тогда это и выплыло. Поменял на

 A:=CreateEvent(nil,true,false,PChar('Updator'));
 try
   FUpdator.StopEvent:=A;
   FUpdator.Resume;
   Repeat
     D:=WaitForSingleObject(A,5000)
   until (D=Wait_Object_0) OR (D=WAIT_ABANDONED)
 finally
   CloseHandle(A)
 end;    

а затем задался сим вопросом.


Aleksandr.   (2004-09-21 16:16:00) [29]

KSergey ©  :
Увы, моду диктуют цели. Надо же, чтобы приложение не выглядило повисшим, пока что-то им делается.


clickmaker   (2004-09-21 16:16:00) [30]

Есть альтернатива потоку - Application.ProcessMessages()
Но если фоновая операция достаточно трудоемкая и, тем более, непрерывная, то лучше поток


Aleksandr.   (2004-09-21 16:14:00) [31]

Млин. А как же быть с визуализацией - прогрессбаром в этом окне, например, показывающем процент выполнения потоком задач, который обновляется тоже сообщениями, посылаемыми из потока?


KSergey   (2004-09-21 16:14:00) [32]

модельное = модальное


KSergey   (2004-09-21 16:13:00) [33]

Да просто сделать модельное окно - вот и все. Как поток заканчивается - шлем окну WM_CLOSE

Вот только мне упорно не понятна эта мода на потоки... Прога все равно стоит на месте - на кой тогда этот поток-то нужен??? Мода?


clickmaker   (2004-09-21 16:11:00) [34]

Не будет
Если нужно узнать о завершении потока, можно просто послать окну соответствующее сообщение


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо