Форум: "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