Текущий архив: 2007.02.11;
Скачать: CL | DM;
ВнизИспользование функции MsgWaitForMultipleObjects Найти похожие ветки
← →
Riply © (2007-01-24 03:11) [0]Здравствуйте !
Натолкнулась в одной из веток форума на сабжевую функцию
и очень обрадовалась. Оказывается можно одной функцией ждать
и событие и сообщение, а не извращаться как я с комбинированием
PeekMessage и WaitForMultipleObjects. Вот здорово !
Но не тут-то было.
Совершенно неожиданно оказалось, что чтобы наслаждаться преимуществами этой функции,
надо, сначала, научиться правильно ею пользоваться :)
А вот тут и вышла загвоздка.
Берем следующую функцию:function MsgWaitThread(pParam: Pointer): DWord;
var
Msg: TMsg;
begin
Result := 0;
while MsgWaitForMultipleObjects(1, PDWord(pParam)^, False, 10000, QS_POSTMESSAGE) = WAIT_OBJECT_0 + 1 do
while PeekMessage(Msg, INVALID_HANDLE_VALUE, 0, WAIT_MSG_BASE + 1, PM_REMOVE) do
if Msg.message = WAIT_MSG_BASE then
begin
Sleep(1000);// что-то делаем
SetErrorList(IntToStr(Msg.lParam)); // Сохраняет строку в файл
end;
SetErrorList("End Thread");
end;
и начинаем ей посылать сообщения:hStopEvent := CreateEvent(nil, True, False, nil);
hThread := BeginThread(nil, 0, @MsgWaitThread, @hStopEvent, 0, ThreadID);
//.....
PostThreadMessage(ThreadID, WAIT_MSG_BASE, WAIT_MSG_WORK, 1);
PostThreadMessage(ThreadID, WAIT_MSG_BASE, WAIT_MSG_WORK, 2);
PostThreadMessage(ThreadID, WAIT_MSG_BASE, WAIT_MSG_WORK, 3);
PostThreadMessage(ThreadID, WAIT_MSG_BASE, WAIT_MSG_WORK, 4);
SetEvent(hStopEvent);
PostThreadMessage(ThreadID, WAIT_MSG_BASE, WAIT_MSG_WORK, 5);
В данном варианте мы принимаем все сообщения (1,2,3,4,5), но крутимся в цикле
"while PeekMessage" и совершенно не реагируем на SetEvent(hStopEvent)
пока не выберем все из очереди, что не есть хорошо :).
Проверять внутри этого цикла hStopEvent - возвращаться к старым "извращениям"
Попытка заменить "while PeekMessage" на "if PeekMessage",
в надежне, что MsgWaitForMultipleObjects проверит состояние hStopEvent,
и мы вернемся к нашей обработке, приводит к потере сообщений от PostThreadMessage.
В зависимости от расположения звезд, получаем от одного до трех первых.
Как можно, спокойно напевая песенку и не торопясь, обрабатывать поступающие команды,
но при первой же опасности (hStopEvent) быстро убегать ?
← →
Сергей М. © (2007-01-24 08:31) [1]
while True do
case MsgWaitForMultipleObjects(1, PDWord(pParam)^, False, 10000, QS_POSTMESSAGE) of
WAIT_OBJECT_0: Break; //дождались события
WAIT_OBJECT_0 + 1: //в очереди есть как минимум одно сообщение
begin
PeekMessage(...) ; //берем одно сообщение из головы очереди
.. //и обрабатываем его
end;
WAIT_TIMEOUT: Break; //не дождались события
end;
← →
Игорь Шевченко © (2007-01-24 10:47) [2]
while not FTerminated do begin
WaitResult := MsgWaitForMultipleObjectsEx(1, FExternalControlEvent,
INFINITE, QS_POSTMESSAGE, 0);
if WaitResult = WAIT_OBJECT_0 then begin
FTerminated := true;
Break;
end else
while PeekMessage(AMsg, INVALID_HANDLE_VALUE, 0, 0, PM_REMOVE) and
not FTerminated do
if AMsg.message = UM_INCOMINGFILE then
ProcessFile(PString(AMsg.lParam))
else if AMsg.message = UM_ERROR then
HandleError(PString(AMsg.lParam));
end;
← →
Riply © (2007-01-24 23:22) [3]Спасибо всем! Вроде получилось разобраться.
P.S. Мне надо было внимательнее читать Help.
"Note MsgWaitForMultipleObjects does not return if there is unread input
of the specified type in the message queue after the thread has called a
function to check the queue. This is because functions such as PeekMessage,
GetMessage, GetQueueStatus, and WaitMessage check the queue and then change
the state information for the queue so that the input is no longer considered new.
A subsequent call to MsgWaitForMultipleObjects will not return until new input
of the specified type arrives. The existing unread input (received prior
to the last time the thread checked the queue) is ignored."
Который раз убеждаюсь, что "посылание в MSDN" - один из самых грамотных ответов :))
P.S.S. Правда не очень уютно, когда тебя туда посылают :))
Страницы: 1 вся ветка
Текущий архив: 2007.02.11;
Скачать: CL | DM;
Память: 0.45 MB
Время: 0.041 c