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

Вниз

Посылка сообщения в Thread   Найти похожие ветки 

 
eSKey   (2002-05-27 18:11) [0]

Дурной наверно вопрос, но все таки - можно ли обмениваться сообщениями (т.е. message) между нитями программы, и как это осуществляется?
У меня имеется тред, который должен постоянно ожидать команд от основного треда, и обработав команду послать уведомление в основной тред. Сейчас это сделано очень тупо и некрасиво - в цикле проверяется переменная-флаг. Есессно, даже при processmessages получается 100% загрузка процессора. Вообщем, очень нужна ваша помощь!


 
Юрий Зотов ©   (2002-05-27 19:09) [1]

Чтобы получать сообщения, поток должен иметь цикл их выборки из очереди (поскольку она своя для каждого потока). Стандартная Delphi-программа имеет такой цикл лишь для главного потока (Application.Run и т.д.), а для остальных ее нужно реализовывать ручками (поэтому VCL и является однопоточной, а в класс TThread введена поддержка выполнения кода в главном потоке - Synchronize).

Но можно решить Вашу задачу и по-другому - через объекты синхронизации (например, критические секции - см. TCriticalSection в справке Delphi). Схема, например, такая.

1. В самом начале программы главный поток (ГП) захватывает объект, запускает дополнительный поток (ДП) и продолжает свою работу.

2. ДП в своем цикле доходит до обработки данных, но сначала пытается захватить объект (а поскольку он уже захвачен ГП, то ДП будет ждать его освобождения - вот она, разгрузка CPU);

3. Когда нужно, ГП готовит данные, освобождает объект (при этом ДП выходит из ожидания) и продолжает свою работу.

4. Выйдя из ожидания, ДП захватывает объект, обрабатывает данные, освобождает объект и посылает сообщение в ГП (через SendMessage - тогда он будет ждать возврата, что и требуется);

5. Получив сообщение, ГП снова захватывает объект и продолжает свою работу (ДП выходит из ожидания SendMessage).

6. Все повторяется начиная с п.2.

7. Перед завершением программы ГП должен освободить объект (чтобы разморозить ДП) и тут же уничтожить ДП.


 
eSKey   (2002-05-27 19:28) [2]

Поправьте, если чего не правильно понял:

type
TMyCommObj = class (TObject)
commandstr:string;
commandparam:string;
ComFormHandle:hwnd;
end;

TMyThread.execute;
begin
while not Terminated do begin
if MyCommObj.Lock //эээ... не помню, имеет TObject такой метод?
then ProcessCommand(MyCommObj);
MyCommObj.UnLock;
sendmessage(MyCommObj.ComFormHandle,...);
Application.processmessages
end;
end;


Что-то вроде этого? Или есть ошибка, а то набросал прямо щас...


 
Юрий Зотов ©   (2002-05-27 20:11) [3]

Понятие "объект" существует не только в Delphi. В Windows есть объекты ядра, а среди них есть объекты синхронизации. Их и надо использовать. В Delphi один из таких объектов реализован в виде класса TCriticalSection (см. справку).

В общем, примерно так:

while not Terminated do
begin
// ДП ждет, когда ГП подготовит данные и освободит объект,
// а затем захватывает его и обрабатывает данные.
MyCriticalSection.Enter;
try
... // Обработка данных - объект остается захваченным ДП.
finally
MyCriticalSection.Leave // ДП освобождает объект.
end;
// ДП уведомляет ГП - а тот снова захватывает объект.
// После возврата из SendMessage ДП повторяет цикл,
// проверяя Terminated и дожидаясь освобождения объекта.
SendMessage(Form1.Handle, ...);
end;


 
eSKey   (2002-05-27 20:31) [4]

Спасибо!


 
jedi   (2002-05-27 20:34) [5]

Esli ya vas pravilino poneal to delaestea ato o4eni prosto:

1. potok zodaiotsea v sostaianii suspended(MyThread.Create(True);)
2. V osnovnom potoke ustanavlivaiutsea zna4enia nekotirih polei obyavlenih v razdele public obiecta potoka. i vizivatsea resume
(MyTheread.Resume()).
3. V execute potoka viponestea 4toto v zvisimosti aot ustonovklennih zna4enii polei iz razdela punlic, ustanovlenih v glavnom potoke i potom potok opeati popadaet v sostaianii suspend vizovom protseduri Suspend(MyTheread.Suspend());
poka v glovnom potoke ne povtoretsea 2 i 3 punkt.
vot malenkii primer:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type


TMyTheread = class(TThread)
private
Res: string;
procedure ShowResult;
protected
procedure Execute; override;
public
AValue: Integer;
constructor Create;
end;

TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Label1: TLabel;
Edit2: TEdit;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }

end;



var
Form1: TForm1;
MyTheread: TMyTheread;

implementation

{$R *.dfm}



constructor TMyTheread.Create;
begin
inherited Create(True);

end;

procedure TMyTheread.Execute;
begin
while not Terminated do
begin
try
Res := IntToStr(AValue + 100);

except
on E: Exception do
Res := E.Message;
end;
Synchronize(ShowResult);
Suspend();
end;

end;

procedure TMyTheread.ShowResult;
begin
try
Form1.Edit2.Text := Res;
except
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if MyTheread.Suspended then
begin
MyTheread.AValue := StrToInt(Edit1.Text);
MyTheread.Resume();
end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
MyTheread := TMyTheread.Create();
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
MyTheread.Terminate();
MyTheread.Resume();
MyTheread.WaitFor();
FreeAndNil(MyTheread);
end;

end.

esli nujen bolee podrobnii primer mogu prislat" po email-u


 
eSKey   (2002-05-27 20:44) [6]


> jedi

suspend кажется не подходит - у меня в треде сидит СокетСервер, который с клиентами работает, и при этом должен получать команды из основного потока.


 
NailS ©   (2002-05-28 12:26) [7]

eSKey (27.05.02 18:11)
Дурной наверно вопрос, но все таки - можно ли обмениваться сообщениями (т.е. message) между нитями программы, и как это осуществляется?

Можно.

BOOL PostThreadMessage(
DWORD idThread, // thread identifier
UINT Msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);

BOOL PeekMessage(
LPMSG lpMsg, // message information
HWND hWnd, // handle to window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax, // last message
UINT wRemoveMsg // removal options
);

BOOL GetMessage(
LPMSG lpMsg, // message information
HWND hWnd, // handle to window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
);




Страницы: 1 вся ветка

Текущий архив: 2002.06.06;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.01 c
6-18088
Quadro
2002-03-25 12:29
2002.06.06
Smart Whois


3-17760
Ammy
2002-05-14 17:09
2002.06.06
фильтр по Calculated Fields


1-17950
jonik pegas
2002-05-28 10:05
2002.06.06
Визуальный компонент подобный Object Inspector-у


3-17764
HydraMarat
2002-05-14 18:18
2002.06.06
Create dBase, Paradox, etc.


1-18006
radisheva
2002-05-24 10:30
2002.06.06
Типы данных