Форум: "Основная";
Текущий архив: 2002.06.06;
Скачать: [xml.tar.bz2];
ВнизПосылка сообщения в 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;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.011 c