Форум: "Основная";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];
ВнизПотоки: запутался с обработчиком событий Найти похожие ветки
← →
NailMan (2004-01-28 13:11) [0]Создаю свою систему событий, которая облуживает различные процессы в игре. Суть ее использования:
- имеется обработчик(пайп) событий
- первая объект ему передает сообщение: запрос у другого объекта(в другом модуле) на получение от него каких-то данных.
- обработчик(пайп) снимает из стека сообщение и на основе его ID вызывает процедуру передачи данных у второго объекта.
- у обработчика есть внутренний кэш на 1 мег.
- второй объект в своей процедуре передачи данных(немножко совсем) запрашивает у обработчика указательно на кэш, врисовывает в него свои данные и посылает сообщение в пайп что мол данные записал - "пользуйтесь"
- с момента когда первый объект послал запрос, он крутится в цикле опрашивая пайп на наличие у него сообщения-подтверждения, который должен послать второй объект после заливки данных. Когда такое сообщение появилось, то первфй объект сливает с него данные.
Вобщем сделал систему не на потоках а просто создав класс обработчика и после послания первым объектом сообщения-запроса, объект вручную вызывает UTPipe.ProcessingMessages, где все эти сообщения обрабатываются(вызываются соотвествующие методы у соотвествующих объектов). Работает в целом гладко. Но...
Хочется автоматизма, тоесть создать обработчик-пайп классом-потоком, который бы при получении сообщения автоматически бы его обрабатывал. При этом класс пославший запрос и требующий получения ответа с удаленной стороны(через пайп) должен опрашивать пайп на наличие ответа. Вобщем сделал пайп так:
TSystemMessagePipe = CLASS (TThread)
Private
Pipe : TMessagePipe;
MessageCount : integer;
PipeLocked : Boolean;
PipeData : Pointer;
Protected
procedure Execute; override;
Procedure DoProcessingMessages;
Public
Constructor Create;
Destructor Destroy;override;
Procedure Push(Msg:TPipeMessage);
Function Pop:TPipeMessage;
Function CheckMessage(msgID:Cardinal):boolean;
Function GetPipePtr(var Ptr:Pointer):Boolean;
END;
Constructor TSystemMessagePipe.Create;
begin
Pipe:=nil;
MessageCount:=0;
GetMem(PipeData,1024 * 1024);
PipeLocked:=false;
FreeOnTerminate := False;
inherited Create(False);
end;
Destructor TSystemMessagePipe.Destroy;
begin
FreeMem(PipeData);
Pipe:=nil;
inherited;
end;
Procedure TSystemMessagePipe.DoProcessingMessages;
var Msg:TPipeMessage;
begin
if MessageCount>0 then
begin
msg:=Pop;
Case msg.ID of
MSG_SCENE_GETACTORSLIST : Scene.ActorsEnumerate;
MSG_SCENE_SET_ACTOR_ANGV : Scene.ActorSetANGV(msg.WParam);
end;
end;
end;
Procedure TSystemMessagePipe.Execute;
begin
DoProcessingMessages;
end;
Вобщем сей поток не получается автоматизировать(DoProcessingMessages как я понял вызывается один раз), т.е. чтобы он автоматически опрашивал свой пайп с сообщениями и обрабатывал их без "подталкиваний".
Как сделать так чтобы обработчик крутился сам по себе обрабатывая сообщения, и вызвавший объект крутился бы в ожидании ответа и все бы это не зависло.
Пробовал так:
Procedure TSystemMessagePipe.Execute;
begin
repeat
DoProcessingMessages;
until 1=2;
end;
После того как отработается сообщение MSG_SCENE_GETACTORSLIST благополучно зависает на это цикле. Если же в оригинале, то от отрабатывается один раз.
В чем грабли? Может хоть кто-нить толково русским языком объяснить как эти потоки пашут и как их сделать автономными?
Вобщем хочется что-то типа WndProc.
ЗЫ: VCL в проге не используется.
← →
Digitman (2004-01-28 13:19) [1]из кода не видно, кто, когда и как посылает код.потоку какие-то "сообщения" ... а от этого и рекомендации соответствующие зависят
← →
MBo (2004-01-28 13:20) [2]1. Книга Рихтера
2 сырой перевод:
http://mbo88.narod.ru/threads.htm
кажется, в примерах есть нечто подобное твоей задаче.
← →
NailMan (2004-01-28 13:59) [3]Digitman ©
окей, вот код первого объекта посылающего запрос на получение данных
Procedure TUTGameConsole.EnumActors;
var
i:integer;
ActorCount:integer;
Act:PActorInfo;
p:pointer;
begin
//Говорим пайпу что хотим получить список актеров
UTPipe.Push(SetMessage(MSG_SCENE_GETACTORSLIST,0,0));
//Ждем сообщения что данные об актерах положены в пайп
WaitMessage(MSG_SCENE_TAKEACTORSLIST);
//получаем указатель на кэш пайпа
UTPipe.GetPipePtr(p);
//обрабатываем полученные данные
with UTPipe.Pop do
begin
... //итаем читаем данные из буфера и вносим в консоль
end;
end;
Это код второго объекта.
Procedure TScene.ActorsEnumerate;
var i:integer;
p:pointer;
AI:PActorInfo;
count:integer;
begin
//получаем указатель на блок данных пайпа
//крутимся пока кэш пайпа свободен для чтения/записи.
WaitPipePtr(p);
ai:=p;
//пишем в пайп данные об актерах
count:=0;
For i:=0 to MaxActors-1 do
if ActorIsExist(i) then
begin
ActorGetInfo(i,ai^.Gbasic,ai^.Name);
inc(count);
end;
//посылаем пайпу сообщение что запрос обработан-данные записаны
UTPipe.Push(SetMessage(MSG_SCENE_TAKEACTORSLIST,count,0));
end;
← →
Digitman (2004-01-28 14:05) [4]этот код мне ни о чем не говорит
я не знаю, что из себя представляет объект UTPipe, что происходит в его методе Push и что делается внутри некоей проц-ры SetMessage()
← →
NailMan (2004-01-28 14:26) [5]Digitman ©
Хм. ну ладно вот и их код:
Добавляет в список сообщений новое.
Procedure TSystemMessagePipe.Push(Msg:TPipeMessage);
begin
inc(MessageCount);
SetLength(Pipe,MessageCount);
Pipe[MessageCount-1]:=Msg;
end;
Вытаскивает из списка последнее сообщение и убивает его
Function TSystemMessagePipe.Pop:TPipeMessage;
begin
if MessageCount=0 then exit;
Result:=Pipe[MessageCount-1];
DestroyMessage;
end;
Создает запись сообщения по введенным параметрам.
Function SetMessage(aMsg:Integer;aWParam:Integer;aLParam:Cardinal):TPipeMessage;
begin
result.ID:=aMsg;
result.WParam:=awparam;
result.LParam:=alparam;
end;
Собсно тут все работает нормально, когда обработчик выполнет не в виде потока(с ручным вызовом DoProcessingMessages после посыла консолью сообщения MSG_SCENE_GETACTORSLIST).
← →
Polevi (2004-01-28 14:32) [6]код твоей поточной ф-ии мне не нравится, тебе стоит почитать про объекты синхронизации и WaitForXXX, MsgWaitForXXX ф-ии
← →
Digitman (2004-01-28 15:16) [7]
> NailMan © (28.01.04 14:26) [5]
в приведенном коде нет ни намека на "сообщения" или "события"
есть просто LIFO-работа с неким списком неких пользовательских структурированных данных
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.06 c