Форум: "Потрепаться";
Текущий архив: 2004.06.13;
Скачать: [xml.tar.bz2];
ВнизМешают ли потоки ловить сообщения Найти похожие ветки
← →
TUser © (2004-05-25 13:04) [0]В приложении запущен поток, который в некоторый момент оказывается занят таким вот циклом
while FStatus = stWaiting do // FStatus - глобальная переменная в данном юните
sleep(200);
Там же есть форма, которая ловит массаги. Есть процедуры, типа
procedure WMMine(...); message WM_MINE;
...
procedure WMMine(...);
begin
MyThread.Status:=stComplete;
end;
Вроде бы такие сообщения должны ловиться. Но они не ловятся (поток свою работу не заканчивает, бряки в обработчиках сообщений ничего не ловят). Посылаются они точно и по правильному хэндлу - в этом я уверен на 100%. Мешает ли работающий поток ловить сообщения окну в данной программе (при учете, что там есть sleep, и вроде бы основному потоку приложения ничего не мешает извлекать сообщения из очереди)? Если да, то как такое можно обойти.
PS. ProcessMessages в потоке пробовал ставить (хотя это и не хорошо), но бестолку.
PPS. Извините, что в Потрепацу, в Основную не добавилось.
← →
Polevi © (2004-05-25 13:14) [1]потоки не мешают
а сделано криво у тебя
почитай про объекты синхронизации
← →
vuk © (2004-05-25 13:16) [2]А почему бы самому потоку сообщения не ловить?
← →
TUser © (2004-05-25 13:37) [3]
> А почему бы самому потоку сообщения не ловить?
Разницы никакой.
> почитай про объекты синхронизации
А какие лучше использовать? Я знаю, что бывают семафоры, мьютексы, критические секции пр., но раньше никогда такие штуки не делал. И что они должны синхронизировать? Если я правильно понимаю, эти объекты позволяют исключить одновременный доступ нескольких процессов к ресурсу или более обще - не допустить одновременного выполнения определенного кода. Но здесь, вроде два процесса, каждый со своими ресурсами. Поясните, пож-та, зачем здесь нужны эти объекты.
← →
vuk © (2004-05-25 13:41) [4]to TUser © (25.05.04 13:37) [3]:
>Разницы никакой.
Да ну? См. MsgWaitForMultipleObjects
← →
DiamondShark © (2004-05-25 13:43) [5]А кто сообщения посылает?
← →
TUser © (2004-05-25 13:45) [6]
> А кто сообщения посылает?
Другая прога. Тоже моя. Посылает SendMessage"ем, хэндл точно правильный, сообщения тоже.
> >Разницы никакой.
Я имел в виду, что при если послать эти сообщения потоку и ему передать обработчики, то ничего не поменялось. Спасибо, иду читать.
← →
Тимохов © (2004-05-25 13:46) [7]Соглашусь с [1] - криво у тебя сделано.
Один поток не может мешать другому потоку выбирать сообщения из своей очереди.
Приведи код кто посылает сообщение.
Синхронизация здесь имхо не нужна - устанавливать значение fStatus можно без синхронизации.
← →
vuk © (2004-05-25 13:51) [8]Проверка переменной - не очень эффективно, т.к. периодически нужно "будить" поток и проверять, что там происходит. В принципе, в данном случае лучше было бы устроить потоку ожидание события, но можно и при помощи сообщения сделать. :o)
← →
TUser © (2004-05-25 14:11) [9]
> Приведи код кто посылает сообщение.
Прога 1 посылает WM_COPYDATA проге 2. В обработчике в проге 2, читаем хэндл из WParam, что-то делаем, потом посылаем несколько сообщений в прогу 1. Посылаем через SendMessage на тот хэндл, который прочитали. Пробовал даже на HWND_BROADCAST, то бестолку. Сообщения определены как WM_USER + 100/200/300. Неужели из-за того, что процедура является обработчиком какого-то сообщения, она сама посылать уже не может?
PS. Понял, что надо подботать про синхронизацию процессов. Обязательно займусь на досуге.
← →
Тимохов © (2004-05-25 14:14) [10]подботай, но проблема у тебя не в этом :(((
← →
DiamondShark © (2004-05-25 14:21) [11]
> Неужели из-за того, что процедура является обработчиком
> какого-то сообщения, она сама посылать уже не может?
Угу. Во избежание дедлоков.
Попробуй написать везде вместо
SendMessage(la-la-la)
Win32Check( SendMessage(la-la-la) )
← →
Тимохов © (2004-05-25 14:24) [12]
> Посылаем через SendMessage на тот хэндл, который прочитали
Просвети откуда ты прочитываешь хэндл.
ЗЫ
Ты бы потрудиля минут 10 на составление полноценного вопроса с необходимым и достаточным кол-вом кода :)))))
← →
Digitman © (2004-05-25 14:34) [13]
> TUser © (25.05.04 13:04)
> В приложении запущен поток, который в некоторый момент оказывается
> занят таким вот циклом
на здоровье .. какие "занятия" ты потоку дал, тем он и занимается
ты дай ему в цикле (кроме всего прочего) "занятие", ожидающее/выбирающее сообщения, адресованные ему или его окнам - будет твой поток получать/обрабатывать сообщения ...
ожидание сообщений - WaitMessage(), MsgWaitForMultipleObjects()
получение сообщений без ожидания - PeekMessage()
получение сообщений с ожиданием - GetMessage()
← →
Тимохов © (2004-05-25 14:38) [14]
> DiamondShark © (25.05.04 14:21) [11]
какие дедлоки? :))
Может я что-то пропустил в своем образовании.
Мой опыт говорит о том, что в обработчике синхронного сообщения ничего не мешает послать синхронное же сообщение автору первого сообщение. Все будет работать.
← →
DiamondShark © (2004-05-25 14:43) [15]
> Тимохов © (25.05.04 14:38) [14]
>
> > DiamondShark © (25.05.04 14:21) [11]
>
> какие дедлоки? :))
> Может я что-то пропустил в своем образовании.
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, Windows switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.
ЗЫ
С Win32Check я наврал.
← →
TUser © (2004-05-25 14:49) [16]2 [12]
ОК. Вот код, вродедолжно хватить. Скажите, как это сделать на основе пересылки сообщений. Сейчас код выглядит так.
Программа-посылатель
unit Unit1;
....
TLooker = class(TThread)
private
procedure Put;
procedure WmStart(var Msg:TMessage); message WM_STARTINFO;
procedure WmEnd(var Msg:TMessage); message WM_ENDINFO;
procedure WmCopyData(var Msg:TMessage); message WM_COPYDATA;
procedure WmFileEnd(var Msg:TMessage); message WM_FILEEND;
public
FStatus:(stWaiting, stGettingData, stComplete, stFinished, stNone);
res:TKister;
procedure Execute; override;
end;
TKiller = class(TThread)
private
public
T1, T2:TDateTime;
procedure Execute; override;
end;
var
FEExplorer: TFEExplorer;
FEWin:hWND;
// FindEatPath:string;
Looker:TLooker;
Killer:TKiller;
FLength:integer;
FNextIndex:integer;
FResult:TResult;
FPhase:byte;
FPI:PProcessInformation;
...
implementation
procedure Run;
begin
... // CreateProcess
end;
procedure TFEExplorer.Button1Click(Sender: TObject);
var cf:string;
begin
Looker.Resume;
end;
procedure TLooker.Execute;
var cf:string;
i:integer; deb:integer;
SA:PSecurityAttributes;
SI:TSTartUpInfo;
cd:TCopyDataStruct;
DOING:boolean;
d:integer;
begin
while {not finished} and (not Terminated) do begin
cf:={file name}
...
Run;
cd.cbData:=length(cf)+1; cd.lpData:=PChar(cf); cd.dwData:=0;
SendMessage(HWND_BROADCAST{FEWin},WM_COPYDATA,Handle,LongInt(@cd));
Killer.Resume;
repeat
FStatus:=stWaiting; Killer.T1:=now;
while FStatus = stWaiting do begin
sleep(200);
// Application.ProcessMessages;
end;
while (FStatus<>stComplete) and (FStatus<>stFinished) do
sleep(0);
if FStatus<>stComplete then
FStatus:=stNone
else ...
until FStatus = stNone;
Killer.Suspend;
DeleteFile(cf);
end;
end;
procedure TLooker.Put;
var i,j:integer;
begin
// Печать результатов
end;
procedure TLooker.WmStart(var Msg:TMessage);
begin
FStatus:=stGettingData;
FLength:=Msg.LParam;
setLength(Looker.res.Kisters,FLength);
setLength(Looker.res.Scores,FLength);
FNextIndex:=0; FPhase:=0;
FResult:=krFinished;
while not ord(FResult) = Msg.WParam do
inc (FResult);
end;
procedure TLooker.WmEnd(var Msg:TMessage);
begin
FStatus:=stComplete;
if FNextIndex<FLength*3 then
begin end; // do something
end;
procedure TLooker.WmCopyData(var Msg:TMessage);
var cd:PCopyDataStruct;
s:string;
begin
if (FStatus = stGettingData) and (FEWin = Msg.WParam) then begin
cd:=PCopyDataStruct(Msg.LParam);
if FPhase<4 then
Looker.res.Kisters[FNextIndex,FPhase]:=PChar(cd.lpData)
else Looker.res.Scores[FNextIndex]:=Double(cd.lpData^);
inc(FPhase);
if FPhase = 5 then begin
inc(FNextIndex);
FPhase:=0;
end;
end;
end;
procedure TLooker.WmFileEnd(var Msg:TMessage);
begin
FStatus:=stFinished;
end;
procedure TKiller.Execute;
begin
while not Terminated do begin
sleep(2000);
T2:=now;
if SecondsBetween(T1,T2) > 5*60 then begin
// restart
TerminateProcess(FPI^.hProcess,0);
Looker.FStatus:=stNone;
end;
end;
end;
....
Программао-получательprocedure SendResults(IsFinishing:boolean; Handle:hWND;Result:TKister);
var i,j:integer; d:double;
cd:TCopyDataStruct;
begin
SendMessage({HWND_BROADCAST}Handle,{WM_DONE}WM_STARTINFO,ord(result.Result),result.Size);
for i:=0 to result.Size-1 do begin
for j:=0 to 3 do begin
cd.dwData:=0; cd.cbData:=system.length(result.Kisters[i,j])+1;
cd.lpData:=PChar(result.Kisters[i,j]);
SendMessage({HWND_BROADCAST}Handle,WM_COPYDATA,Handle,LongInt(@cd));
end;
d:=Scores[i];
cd.dwData:=0; cd.cbData:=sizeof(Double); cd.lpData:=@d;
end;
if IsFinishing then
SendMessage({HWND_BROADCAST}Handle,WM_ENDINFO,0,0)
else SendMessage({HWND_BROADCAST}Handle,WM_FILEEND,0,0);
end;
procedure TFindEatWindow.AnalizeFile(var Msg:TMessage);
var FName:PChar;
result:TKister;
ic,im:integer; i,j:integer;
m:TModel; h:hWND;
cd:TCopyDataStruct;
d:double;
begin
FName:=PChar(PCopyDataStruct(Msg.LParam)^.lpData);
h:=Msg.WParam;
if FileExists(FName) then begin
if assigned(Prot) then begin
Prot.Free;
Prot:=nil;
end;
Prot:=TProtein.Create;
try
with Prot do begin
FileName:=FName;
Parse;
// finding
for ic:=0 to ChCount-1 do begin
result.Result:=krUnknownError;
if Chains[ic].ModCount>0 then begin
im:=0;
m:=Chains[ic].Models[im];
FindBeta(m);
FindKisters(m);
result.Result:=krFinished;
result.Size:=system.length(Pairs);
setLength(result.Kisters,result.Size);
setLength(result.Scores,result.Size);
for i:=0 to result.Size-1 do begin
result.Scores[i]:=Scores[i];
for j:=0 to 3 do
result.Kisters[i,j]:=m.Residues[Pairs[i,j]].ShortName+
inttostr(m.Residues[Pairs[i,j]].Position)+"("+
inttostr(m.Residues[Pairs[i,j]].Number)+")"+
m.Residues[Pairs[i,j]+2].ShortName+
inttostr(m.Residues[Pairs[i,j]+2].Position)+"("+
inttostr(m.Residues[Pairs[i,j]+2].Number)+")";
end;
result.Result:=krFinished;
end;
SendResults(ic<chcount-1,h,result);
end;
end;
← →
TUser © (2004-05-25 14:51) [17]
> If the specified window was created by a different thread
Нет, это обычное окно. TForm. Процедура окна д.б. создана.
← →
Digitman © (2004-05-25 14:53) [18]
> Программао-получатель
> ... SendMessage
это что за "получатель" такой, который send-ф-цию вызывает ?)
← →
Тимохов © (2004-05-25 14:56) [19]
> TUser © (25.05.04 14:51) [17]
Уважаемый. Вы тут полную ерунду делаете.
Вы хотите, чтобы в поток приходило сообщение? Я тоже хочу, но обычно я для этого очередь выборки сообщений делаю. Каким чудесным образом в TLooker вызовется хоть одно сообщение?
Для этого нужно сделать очередь выборки сообщений (см. в forms по строке поиска peekmessage). К тому же должен быть dispatch.
Я готовы был вам помочь, но сейчас нет - т.к. нужно фактически за вас все переписать. :(((
← →
TUser © (2004-05-25 14:58) [20]Это условные названия. Они оба и получают и отсылают сообщения. Только посылатель не ловит сообщения, отправляемые получателем. Можно было бы их назвать "Контроллер" и "Основная программа"
← →
Тимохов © (2004-05-25 14:59) [21]Автору.
Если вы хотите именно синхронные сообщения посылать, то нужно делать окно с оконной процедурой. Иначе вы такое сообщение не обработатете. Окно делать можно через AllocateHWnd.
Огномный совет: прочитет 26 главу рихтера изд 4 про очередь сообщение. Очень будет полезно...
← →
TUser © (2004-05-25 15:02) [22]Раньше сообщения ловила форма. Точнее тоже не ловила. Переделал в поток после [2]. Тогда это выглядело так. FStatus была глобальной переменной для этого модуля, а обработчики сообщений были описаны в классе TFEExplorer. Соотвественно было написано SendMessahe(FEWin,WM_COPYDATA,FEExplorer.Handle,...)
← →
Тимохов © (2004-05-25 15:02) [23]
> TUser © (25.05.04 14:58) [20]
при чем здесь названия? :))
Где у вас в tlooker получение сообщения?
← →
Digitman © (2004-05-25 15:03) [24]
> посылатель не ловит сообщения, отправляемые получателем
для того чтобы он, получатель, их "ловил", см. [13]
либо, если GUI-приложение на базе VCL и "ловец" - осн.код.поток, см. Application.Processmessages
← →
TUser © (2004-05-25 15:03) [25]
> при чем здесь названия? :))
Это я на [18] отвечал. Ваш пост тогда не читал еще.
← →
DiamondShark © (2004-05-25 15:06) [26]
> TLooker = class(TThread)
> private
> procedure Put;
>
> procedure WmStart(var Msg:TMessage); message WM_STARTINFO;
> procedure WmEnd(var Msg:TMessage); message WM_ENDINFO;
> procedure WmCopyData(var Msg:TMessage); message WM_COPYDATA;
> procedure WmFileEnd(var Msg:TMessage); message WM_FILEEND;
> public
> FStatus:(stWaiting, stGettingData, stComplete, stFinished,
> stNone);
> res:TKister;
> procedure Execute; override;
> end;
А можно объяснить, что тут имелось в виду? Нужто ожидалось, что процедуры Wm* буду вызываться?
Мама моя родная! Тут такое непонимание наворочено, что даже не знаешь, за что браться...
Давай так начнём. Что надо получить? Самыми общими словами.
← →
Digitman © (2004-05-25 15:19) [27]
> TUser © (25.05.04 14:51) [17]
1. Sendmessage(HWND_BROADCAST) не может послать сообщение именно потоку - эта ф-ция предназначена для синхр.посылки сообщений ОКНАМ, которые поток потенциально может создать, вызывая, например, CreateWindow(Ex)
2. Для того чтобы код.поток мог ожидать+выбирать+обрабатывать в некий нужный момент времени сообщения, адресованные ему либо ЕГО ОКНАМ, он должен в нужный момент времени выполнить хотя бы один раз хотя бы следующее :
if GetMessage(Msg, 0, ..) then
if Msg.hWnd <> 0 then
begin
//Translatemessage(Msg); как правило, бессмысленно для неосн.код.потока
DispatchMessage(Msg); //обработка сообщений, адресованных ОКНАМ потока
end
else
Dispatch(Msg.message); //обработка сообщений (посланных by PostThreadMessage) САМОМУ потоку как объекту-наследнику TObject
← →
TUser © (2004-05-25 15:27) [28]Видать, рано мне такие штуки творить. Сделаю как-нибудь попроще и пойду читать Рихтера и иже с ним.
Всем спасибо.
← →
Тимохов © (2004-05-25 15:29) [29]
> TUser © (25.05.04 15:27) [28]
начни прямо с указанной мной главы.
я так и делал - очень хорошо понял, не зная совсем ни синхронизацию, ни потоки.
я их потом прочел.
← →
Digitman © (2004-05-25 15:30) [30]
> пойду читать Рихтера и иже с ним
сие весьма отрадно
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.06.13;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.036 c