Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];




Вниз

Нити 


SPeller   (2002-03-28 08:59) [0]

Помогите разобраться в нитях. Проблема такова - создаю нить, в которой описываю некоторыю функцию. Функция бесконечна. При её вызове основная программа виснет, как если бы эта функция была в ней. Нить ведь должна выполняться отдель от основной, что я не так делаю? Подскажите..

type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure MyProcedure;
public
procedure Execute; override;
end;

implementation

procedure TMyThread.Execute;
begin
Synchronize(MyProcedure);
end;

procedure Tmythread.MyProcedure;
begin
// Бесконечный код
end;

В модуле формы, откуда вызываю:

procedure TfrmMain.FormCreate(Sender: TObject);
begin
thread1:=tmythread.create(true);
end;

procedure TfrmMain.FormDblClick(Sender: TObject);
begin
thread1.Execute;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
thread1.Free;
end;



MBo   (2002-03-28 09:04) [1]

Sinchronize надо те участки кода, которые обращаются к главному потоку.



Виктор Щербаков   (2002-03-28 09:06) [2]

Всё правильно. Tmythread.MyProcedure будет выполняться в основном потоке т.к. ты используешь Synchronize.



gek   (2002-03-28 09:08) [3]

procedure TfrmMain.FormCreate(Sender: TObject);
begin
thread1:=tmythread.create(true);
thread1.priority:=tpLower;
end;

procedure TfrmMain.FormDblClick(Sender: TObject);
begin
thread1.Resume;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
thread1.suspend;
thread1.Free;
end



dymka   (2002-03-28 09:09) [4]

процедура переданная в методе Synchronize выполняется в КОНТЕКСТЕ ОСНОВНОГО ПОТОКА ПРИЛОЖЕНИЯ!
Весь код потока должен размещаться в теле Execute, либо вызываться без метода Synchronize!!! Это метод нужен для синхронизации твоего потока и основного потока, например обновление компонентов VCL итп..
Запускать поток нужно конструктором Create, где в качестве параметра передавать False, если поток нужно запустить немедленно, и True, если запустить его ты хочешь позже..
далее.. в теле Execute сделай следующее:
FreeOnTerminate := True; тогда при терминировании потока
он автоматически освободит свои ресурсы...
терминирую поток не вызовом Free, а вызовом метода Terminate,
Внутри потока используй проверку на терминирование - свойство Terminated...



dymka   (2002-03-28 09:12) [5]

код должен быть такой
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure MyProcedure;
public
procedure Execute; override;
end;

implementation

procedure TMyThread.Execute;
begin
FreeOnTerminate := True;
MyProcedure;
end;

procedure Tmythread.MyProcedure;
begin
// Бесконечный код
...
if Terminated then Break;
...
end;

В модуле формы, откуда вызываю:

procedure TfrmMain.FormCreate(Sender: TObject);
begin
thread1 := tmythread.create(True);
end;

procedure TfrmMain.FormDblClick(Sender: TObject);
begin
thread1.Suspend;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
thread1.Terminate;
end;



panov   (2002-03-28 09:14) [6]

procedure TMyThread.Execute;
begin while not Terminated do
begin
//здесь делаем полезную работу.
//а также проверяем if Terminated then Break;
//если нужно обновить данные в основном потоке, вызываем метод Synchronize
end;
end;



panov   (2002-03-28 09:16) [7]

>dymka © (28.03.02 09:12)

procedure Tmythread.MyProcedure;
begin
// Бесконечный код
...
if Terminated then Break; - выполнять надо в Execute;
...
end;



dymka   (2002-03-28 09:24) [8]

2 panov:
Вовсе нет, т.к. MyProcedure выполняется в потоке, управление будет передано обратно в Execute, где поток и завершит свое выполнение, закончив Execute...



SPeller   (2002-03-28 09:45) [9]

Спасибо, работает.
Но тут вот возникла другая проблема. Суть полезной работы нити в постоянном рисовании в контекст формы. При попытке перемещения формы изображение начинает хаотично рисоваться по всему экрану (не постоянно хаотично, а передвинул форму - в новом месте), и рисуется по одному кадру, но иногда можно увидеть и движение. Рисуестся то боком на форме, то за формой, то ещё где-нибудь. При этом окна других приложений почти не перерисовываютя, и остаются белые пятна (фон моего изображения белый). Кто знает, что это за баги такие ??



dymka   (2002-03-28 09:58) [10]

Как рисуешь? На канве??? или еще на чем???
Рисуешь в контексте основного потока? или в своем потоке?



gek   (2002-03-28 10:01) [11]

Наверное Canvas.Lock при перемещении
и Canvas.UnLock при прекращении перемещения.
Может поможет.



SPeller   (2002-03-28 10:05) [12]

Беру непосредственно DC (Canvas.Handle), т.к. рисую через API. Мне надо, чтобы рисование происходило и при перемещении окна.



dymka   (2002-03-28 10:09) [13]

тогда рисуй лучше на TBitmap или подобном...



SPeller   (2002-03-28 10:15) [14]

Я ошибся, рисую не сразу на самом DC формы а на временном, после чего копирую содержимое второго в первый.



SPeller   (2002-03-28 12:13) [15]

Я нашёл, в чём проблема! ОКАЗЫВАЕТСЯ, рисование в контексте формы и в контексте канвы -- это ДВЕ РАЗНЫЕ вещи !!! Стал рисовать в dc, полученном из GetDC(Form.Handle) и всё стало чику-пуки и никаких косяков! Выходит, что канва формы никак не связана с самой формой, разве что координатами..



dymka   (2002-03-28 12:28) [16]

:)




Форум: "Основная";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.08;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.74 MB
Время: 0.019 c
14-22811          Miwa                  2002-02-26 18:29  2002.04.08  
undelete/unerase


1-22683           Сатир                 2002-03-26 13:37  2002.04.08  
Получение списка экспортируемых функций


3-22593           Alexandr              2002-03-18 10:49  2002.04.08  
Дастать данные из Access


1-22684           lipskiy               2002-03-24 23:23  2002.04.08  
TThread: Что значит ошибка


3-22602           AndrewK               2002-03-18 12:44  2002.04.08  
Сортировка в DbGrid