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

Вниз

Будет ли форма получать и обрабатывать сообщения при ожидании?   Найти похожие ветки 

 
Aleksandr.   (2004-09-21 16:08) [0]

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


 
clickmaker ©   (2004-09-21 16:11) [1]

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


 
KSergey ©   (2004-09-21 16:13) [2]

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

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


 
KSergey ©   (2004-09-21 16:14) [3]

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


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

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


 
clickmaker ©   (2004-09-21 16:16) [5]

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


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

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


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

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;    

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


 
Digitman ©   (2004-09-21 16:21) [8]


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


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


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

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


 
Digitman ©   (2004-09-21 16:49) [10]

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


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

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


 
Digitman ©   (2004-09-21 17:03) [12]


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


именно !


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

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

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;

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


 
KSergey ©   (2004-09-22 11:42) [14]

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

> 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 не задерживается...


 
Digitman ©   (2004-09-22 12:34) [15]

var
Msg: TMsg;
...

while True do
case MsgWaitForMultipleObjects(1,A,false,1000,QS_AllINPUT) of
 Wait_Object_0: Break;
 Wait_Object_0 + 1:
   while Peekmessage(Msg, 0, 0, 0, PM_REMOVE) do
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
end;

и все ! вуаля !


 
Aleksandr.   (2004-09-22 12:40) [16]

Круто! Работает! Спасибо!


 
KSergey ©   (2004-09-22 12:54) [17]

> [15] Digitman ©   (22.09.04 12:34)

Не понимаю, блин....

У меня заработало (если так можно сказать)

pH := 0;  // да хоть что
MsgWaitForMultipleObjects(0, pH, FALSE, INFINITE, QS_ALLINPUT {QS_PAINT});


Т.е., получается, Handle треда передавать туда и вовсе нельзя?? Вроде в примерах - находил..


 
Digitman ©   (2004-09-22 13:18) [18]


> KSergey ©   (22.09.04 12:54) [17]


> получается, Handle треда передавать туда и вовсе нельзя??


что значит "нельзя" ? а для чего ж тогда эта ф-ция вообще существует по-твоему ?

для ожидания ТОЛЬКО сообщений есть Getmessage()
эта же ф-ция предназначена специально для ожидания срабатывания конкретных объектов синхронизации и при этом немедленной реакции на сообщения в очереди трэда, вызывавшего эту ф-цию

иными словами, по функциональности этот вызов эквивалентен "комбинации" вызовов WaitForMultipleObjects и GetMessage


 
Warlock ©   (2004-09-22 13:22) [19]

А если вернуться к цели этой задачи -

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

Можно просто использовать Метод потока Synchronize


 
KSergey ©   (2004-09-22 13:33) [20]

> Warlock ©   (22.09.04 13:22) [19]

Мне кажется, что более оправданным было бы постить сообщения окну с индикатором и через параметры сообщения сообщать сколько процентов.


 
KSergey ©   (2004-09-22 13:35) [21]

> Digitman ©   (22.09.04 13:18) [18]
> > получается, Handle треда передавать туда и вовсе нельзя??
> что значит "нельзя" ? а для чего ж тогда эта ф-ция вообще
> существует по-твоему ?

А фигли она у меня тогда в [14] ошибку возвращает? ;)


 
KSergey ©   (2004-09-22 13:41) [22]

Елки, в моем случае вообще проканала WaitMessage... И как я ее сразу проглядел в ShowModal...


 
Digitman ©   (2004-09-22 13:41) [23]


> А фигли


"фигли", не "фигли" ..

если объектов синхрогизации более одного, 2-м параметром нужно передавать нужно адрес массива хэндлов объектов синхронизации ! .. а 1-м параметром - число эл-тов этого массива ...

вот тогда и не будет никаких "фигли" )


 
KSergey ©   (2004-09-22 13:46) [24]

> Digitman ©   (22.09.04 13:41) [23]

Будьте любезны, гляньте еще раз код из [14]. Что там не верно? Формально?
Приведу еще раз, "избранное":

pH: THandle;
MsgWaitForMultipleObjects(1, pH,


Где я не прав??

PS
Какой гад в дельфи описал второй параметр как var?? Неужели нельзя было нормально указатель воткнуть?


 
Digitman ©   (2004-09-22 13:56) [25]


> Что там не верно? Формально?


конкретно в ЭТОЙ строке "формальных неверностей" как бы не наблюдается ...
Непонятно, что за "нифига" ..


> Какой гад в дельфи описал второй параметр как var?? Неужели
> нельзя было нормально указатель воткнуть?


а в чем сложности-то ?


 
KSergey ©   (2004-09-22 14:09) [26]

> [25] Digitman ©   (22.09.04 13:56)
> > Что там не верно? Формально?
> конкретно в ЭТОЙ строке "формальных неверностей" как бы
> не наблюдается ...
> Непонятно, что за "нифига" ..

Нифига - вот какая штука: первый раз все проходит (смотрим код в [14]).
Второй и последующие возвращается WAIT_FAILED, RaiseLastWin32Error ренерит ошибку "неверный дескриптор, код 6". Значение pH не меняется от вызова к вызову.

Впрочем, возможно я книжки не дочитал.

> > Какой гад в дельфи описал второй параметр как var?? Неужели
> > нельзя было нормально указатель воткнуть?
> а в чем сложности-то ?

Массив как туда запихать? Не, я догадываюсь, что arr[0], но не логично, правда? Просто arr - я не уверен, что верно... Или заблуждаюсь?
Ну да это пол-беды.
А если я динамически выделил память? Есть у меня указатель на ее начало, и что мне передавать в качестве параметра в эту ф-цию, интересно?


 
Digitman ©   (2004-09-22 14:23) [27]


> KSergey ©   (22.09.04 14:09) [26]


во-первых, GetCurrentThread возвращает псевдохэндл тек.трэда

во-вторых, код этот несуразен даже по логике - каков смысл ожидать завершения текущего трэда, если он не завершится пока явно выполняет некий цикл ?


> Массив как туда запихать?


"пихать" ничего никуда не надо - "пихалка" может сломаться

смотря как он, массив, объявлен тобой
конкретно в случае когда F: array[..] of THandle передача его в кач-ве параметра должна выглядеть просто как F


> А если я динамически выделил память?


приводи конкретный пример


 
KSergey ©   (2004-09-22 15:19) [28]

>  [27] Digitman ©   (22.09.04 14:23)
> во-первых, GetCurrentThread возвращает псевдохэндл тек.трэда
> во-вторых, код этот несуразен даже по логике - каков смысл
> ожидать завершения текущего трэда, если он не завершится
> пока явно выполняет некий цикл ?

А я сообение жду, а не завершение треда ;)
Впрочем, наверняка идиотизм, не спорю. WaitMessage мне попалась позже...

смотря как он, массив, объявлен тобой
конкретно в случае когда F: array[..] of THandle передача его в кач-ве параметра должна выглядеть просто как F


А если

F: array of THandle
SetLength(F, ..)


Как тут быть?

> > А если я динамически выделил память?
> приводи конкретный пример

ph: PHandle;
GetMem (Pointer(ph), SizeOf(THandle)*5);  // выделил под 5 элементов
... чем-то заполнил...


Как теперь этот надбор хендлов, на которые указывает ph, передать в MsgWaitForMultipleObjects?


 
Digitman ©   (2004-09-22 15:26) [29]


> сообение жду, а не завершение треда


ну и жди ! тот  же WaitMessage или - что удобней - GetMessage ..


> А если


а "если", то @F[0]


> Как теперь


Pointer(ph)^


 
KSergey ©   (2004-09-22 16:05) [30]

> [29] Digitman ©   (22.09.04 15:26)
> а "если", то @F[0]
> Pointer(ph)^

Я так и подозревал... И зачем такой изврат, вот кто мне скажет?? Ну было бы описано как указатель...

Ну да ладно. Понял. Спасибо.


 
Digitman ©   (2004-09-22 16:11) [31]


> И зачем такой изврат


никакого "изврата"

Борланд вовсе не обязан лепить кучу оверлоуд-функций под каждый "случай твоей жизни" .. "случаев" этих м.б. туева хуча - сегодня ты возжелаешь определить массив как динамический, а завтра ты сподобишься указатель на данные своего массива хранить в нетипиз.указателе или еще х.з. в каком виде ...
что, Борланд таки обязан (?) предугадывать все возможные твои выкрутасы с декларациями ?


 
KSergey ©   (2004-09-22 16:25) [32]

> [31] Digitman ©   (22.09.04 16:11)
> твои выкрутасы с декларациями ?

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

И, к стати, я как-то не уверен на счет @F[0]. Может все же просто F[0]?
А ведь в случае просто указателя было бы как раз @F[0], что логично и естественно. А тут получается (синтаксически) как будто первый элемент передаю, по ссылке. А то, что при этом на самом деле указатель передается, подразумевающмйся как указатель на все "тело" массива - не слишком ли много подразумеваний??

Да, речь веду лишь про ф-ции WinAPI, т.к. в дельфийских библиотеках уже как раз все нормально, понятно и естественно.


 
Digitman ©   (2004-09-22 16:32) [33]


> А тут получается (синтаксически)


не получается

Паскаль есть Паскаль

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


 
KSergey ©   (2004-09-22 17:14) [34]

> [33] Digitman ©   (22.09.04 16:32)

Ладно, понял. Спасибо.



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

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

Наверх




Память: 0.57 MB
Время: 0.038 c
14-1096879995
msguns
2004-10-04 12:53
2004.10.24
Как поднять анкету ?


3-1096203236
Vasis
2004-09-26 16:53
2004.10.24
Поле1||Поле2


1-1097563355
Ann_k
2004-10-12 10:42
2004.10.24
Процедуры в datamodule


1-1097091748
bloodman
2004-10-06 23:42
2004.10.24
Как найти TtreeNode по AbsoluteIndex в дереве??


1-1097497654
Jolik
2004-10-11 16:27
2004.10.24
Exception в конструкторе...