Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.035 c
14-16680
}|{yk
2004-01-17 14:11
2004.02.06
Не работает клиент форума


1-16430
snake2003
2004-01-22 12:43
2004.02.06
ComcoBox с изменением размера


1-16275
Пубертанец
2004-01-26 09:23
2004.02.06
Плагины на bpl


1-16481
sashok
2004-01-23 13:26
2004.02.06
Архиватор


1-16507
Zheks
2004-01-27 10:31
2004.02.06
Вопрос про мьютексы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский