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

Вниз

Очередь сообщений   Найти похожие ветки 

 
Цукор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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.01 c
6-1213512971
JanMihail
2008-06-15 10:56
2010.02.28
Как представить тему письма в нормальном виде?


15-1260991862
KilkennyCat
2009-12-16 22:31
2010.02.28
SQL и куча пользователей.


6-1211183591
ivanov
2008-05-19 11:53
2010.02.28
открыватьчужие ссылки в новом окне?


15-1260821412
Elnino
2009-12-14 23:10
2010.02.28
Хранение файлов в БД


15-1261007230
Rouse_
2009-12-17 02:47
2010.02.28
Обучение PHP