Форум: "Начинающим";
Текущий архив: 2010.02.28;
Скачать: [xml.tar.bz2];
ВнизОчередь сообщений Найти похожие ветки
← →
Цукор5 (2009-12-24 15:48) [0]Есть некоторый класс.
В одном из методов данного класса "крутится" очередь сообщений
while GetMessage(Msg,0,0,0) do
begin
...
case Msg.message of
WM_USER+8: что-то
...
end;
Также есть еще один метод, который должен послать сообщение в эту очередь. Очередь приняв эту сообщение должна что-то выполнить И РЕЗУЛЬТАТ ПЕРЕДАТЬ обратно.
Сделал для пробы так :
function TМойКласс.GetAny: String;
FAny:=""; // FANy вынесен в private. Я знаю, что это от Лукавого
PostThreadMessage(FMsgThreadID,WM_USER+8,0,0); // посылаем сообщение
Sleep(100); // ждем
Result:=FAny;
Но это, естественно, неверно. Как правильно дождаться того, что очередь выполнила что-то? И как это что-то(в моем случаи String) передать вызывающему методу ? Есть предположение создать TEvent и дожидаться его выполнения WaitFor - это для определения, что очередь выполнила нужные мне действия. Правильный ли ход моих домыслов ? Но как передать строку ?
← →
Игорь Шевченко © (2009-12-24 16:23) [1]
> Очередь приняв эту сообщение должна что-то выполнить И РЕЗУЛЬТАТ
> ПЕРЕДАТЬ обратно.
Кому ?
← →
Юрий Зотов © (2009-12-24 16:23) [2]Сообщение WM_USER+8 обязательно должно пройти через очередь потока? Нельзя ли послать его через SendMessage какому-нибудь окну? Тогда вопрос решается автоматически.
Другой вариант - при отсылке сообщения его параметром передать Self и уйти в цикл типа этого:
while not Handled do Sleep(1)
где Handled - свойство Self.
После обработки сообщения поток выставляет это свойcтво в TRUE и цикл завершается.
← →
Игорь Шевченко © (2009-12-24 16:24) [3]Для обмена сообщениями с возвратом посылающему используется функция SendMessage, без всякой очереди.
← →
Игорь Шевченко © (2009-12-24 16:28) [4]
> Но это, естественно, неверно. Как правильно дождаться того,
> что очередь выполнила что-то?
если же нужно обязательно прорываться через PostThreadMessage, то тогда разумно поступить так:
1. создать событие с автоматическим сбросом
2. договориться с получателем, где будет лежать результат
3. послать сообщение
4. ждать на этом событии
5. прочитать результат из оговоренного места
получатель, приняв сообщение, кладет результат и устанавливает событие (это если он в отдельном потоке, разумеется :)
← →
Цукор5 (2009-12-24 16:46) [5]2 Игорь Шевченко © (24.12.09 16:28) [4]
НУ...вроде так и сделал. Только "оговоренное место" у меня в private класса определено.
Вот код:
WM_USER+10:
begin
PAny:=PMyAnyData(Msg.wParam);
I:=LineOpen(FLineApp,PAny.ModemID,FLine,TApiV,0,DWord(Self),
LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM,CallParams);
if not TapiFailed(I) then
begin
VarStr := nil;
try
GetMem(VarStr, VarStrAllocSize);
VarStr.dwTotalSize := VarStrAllocSize;
I:=lineGetId(FLine, 0, 0, LINECALLSELECT_LINE, VarStr, "comm/datamodem/portname");
if not TapiFailed(I) then
begin
SetString(PortName, PChar(Cardinal(VarStr) + VarStr.dwStringOffset), VarStr.dwStringSize - 1);
FPortName:=PortName;
end;
finally
FreeMem(VarStr);
end;
end;
SetEvent(PAny.Event);
Dispose(PAny);
end;
function TDial.GetPortModem(ModemID: DWord): String;
var FEvent:THandle;
I:DWord;
Q:PMyAnyData;
begin
FPortName:="";
//
FEvent:=CreateEvent(nil,True,False,"");
New(Q);
Q^.ModemID:=ModemID;
Q^.Event:=FEvent;
PostThreadMessage(FMsgThreadID,WM_USER+10,wParam(Q),0);
while True do
begin
I:=WaitForSingleObject(FEvent,100);
if I=WAIT_OBJECT_0 then Break;
end;
ResetEvent(FEvent);
CloseHandle(FEvent);
//
Result:=FPortName;
end;
← →
Цукор5 (2009-12-24 16:47) [6]Забыл это
type
TMyAnyData = packed record
ModemID:DWord;
Event:THandle;
end;
PMyAnyData = ^TMyAnyData;
← →
Игорь Шевченко © (2009-12-24 17:29) [7]
> while True do
> begin
> I:=WaitForSingleObject(FEvent,100);
> if I=WAIT_OBJECT_0 then Break;
> end;
while True do
begin
I := WaitForSingleObject(FEvent,100)
if I = WAIT_OBJECT_0 then
Break;
else if I <> WAIT_TIMEOUT then
RaiseLastOSError;
end;
иначе при ошибке так и будешь в цикле висеть
← →
Игорь Шевченко © (2009-12-24 17:30) [8]
> ResetEvent(FEvent);
> CloseHandle(FEvent);
Reset не нужно
← →
Игорь Шевченко © (2009-12-24 17:32) [9]кстати, непонятно, зачем вообще нужен цикл для ожидания.
напиши тогда уж
WaitForSingleObject(..., INFINITE)
← →
Цукор5 (2009-12-24 17:44) [10]2 Игорь Шевченко © (24.12.09 17:32) [9]
Все дело в том, что этот метод GetPortModem я вызываю из главной формы.
INFINITE не поставил по причине боязни...а вдруг и вправду сообщение не дойдет или еще что. Я ж буду тогда висеть. Да и с циклом тоже буду висеть))
Даже не знаю что и делать. Но вроде все работает - что, собственно, радует.
← →
Цукор5 (2009-12-24 17:46) [11]2 Игорь Шевченко © (24.12.09 17:30) [8]
> Reset не нужно
Согласен. То "автоматом" случилось.
← →
Игорь Шевченко © (2009-12-24 17:47) [12]
> INFINITE не поставил по причине боязни...а вдруг и вправду
> сообщение не дойдет или еще что
Тогда разумный интервал ожидания
← →
Цукор5 (2009-12-24 17:54) [13]2 Игорь Шевченко © (24.12.09 17:47) [12]
> Тогда разумный интервал ожидания
Да, так и сделал. Низкий Вам поклон !!!
PostThreadMessage(FMsgThreadID,WM_USER+10,wParam(Q),0);
WaitForSingleObject(FEvent,1000);
// уже не важно WAIT_OBJECT_0 или WAIT_TIMEOUT все равно выйдет через 1 сек
CloseHandle(FEvent);
Result:=FPortName;
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.02.28;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.005 c