Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-17961
niko4615
2002-05-28 10:08
2002.06.06
TReeview


1-18049
PEC
2002-05-21 12:33
2002.06.06
Я извиняюсь за вопрос не в тему, но всеже


7-18163
VZV
2002-03-12 15:07
2002.06.06
как напрямую в порт ввода-вывода загнать байт?


1-17922
KvORubin
2002-05-27 09:20
2002.06.06
Проблеммы с кодировками!!!


1-17928
dr0Ne64
2002-05-27 21:26
2002.06.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
Английский Французский Немецкий Итальянский Португальский Русский Испанский