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

Вниз

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

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.036 c
14-1096920771
matt
2004-10-05 00:12
2004.10.24
Рекомендации по построению GUI


9-1087975484
lifo
2004-06-23 11:24
2004.10.24
X files


1-1097147570
Yuri Btr
2004-10-07 15:12
2004.10.24
Вопрос по быстрому преобразованию Фурье


3-1096374715
kolos_rus
2004-09-28 16:31
2004.10.24
Как в тригире использовать данные из другой таблицы


4-1095869036
Антон
2004-09-22 20:03
2004.10.24
GDI: как узнать высоту текстового блока, если ширина задается





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский