![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Нити [D6, WinME]
SPeller © (2002-03-28 08:59:00)Помогите разобраться в нитях. Проблема такова - создаю нить, в которой описываю некоторыю функцию. Функция бесконечна. При её вызове основная программа виснет, как если бы эта функция была в ней. Нить ведь должна выполняться отдель от основной, что я не так делаю? Подскажите..
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;
dymka (2002-03-28 12:28:00) [1]:)
SPeller (2002-03-28 12:13:00) [2]Я нашёл, в чём проблема! ОКАЗЫВАЕТСЯ, рисование в контексте формы и в контексте канвы -- это ДВЕ РАЗНЫЕ вещи !!! Стал рисовать в dc, полученном из GetDC(Form.Handle) и всё стало чику-пуки и никаких косяков! Выходит, что канва формы никак не связана с самой формой, разве что координатами..
SPeller (2002-03-28 10:15:00) [3]Я ошибся, рисую не сразу на самом DC формы а на временном, после чего копирую содержимое второго в первый.
dymka (2002-03-28 10:09:00) [4]тогда рисуй лучше на TBitmap или подобном...
SPeller (2002-03-28 10:05:00) [5]Беру непосредственно DC (Canvas.Handle), т.к. рисую через API. Мне надо, чтобы рисование происходило и при перемещении окна.
gek (2002-03-28 10:01:00) [6]Наверное Canvas.Lock при перемещении
и Canvas.UnLock при прекращении перемещения.
Может поможет.
dymka (2002-03-28 09:58:00) [7]Как рисуешь? На канве??? или еще на чем???
Рисуешь в контексте основного потока? или в своем потоке?
SPeller (2002-03-28 09:45:00) [8]Спасибо, работает.
Но тут вот возникла другая проблема. Суть полезной работы нити в постоянном рисовании в контекст формы. При попытке перемещения формы изображение начинает хаотично рисоваться по всему экрану (не постоянно хаотично, а передвинул форму - в новом месте), и рисуется по одному кадру, но иногда можно увидеть и движение. Рисуестся то боком на форме, то за формой, то ещё где-нибудь. При этом окна других приложений почти не перерисовываютя, и остаются белые пятна (фон моего изображения белый). Кто знает, что это за баги такие ??
dymka (2002-03-28 09:24:00) [9]2 panov:
Вовсе нет, т.к. MyProcedure выполняется в потоке, управление будет передано обратно в Execute, где поток и завершит свое выполнение, закончив Execute...
panov (2002-03-28 09:16:00) [10]>dymka © (28.03.02 09:12)
procedure Tmythread.MyProcedure;
begin
// Бесконечный код
...
if Terminated then Break;- выполнять надо в Execute;
...
end;
panov (2002-03-28 09:14:00) [11]
procedureTMyThread.Execute;
begin while notTerminated do
begin
//здесь делаем полезную работу.
//а также проверяем ifTerminated thenBreak;
//если нужно обновить данные в основном потоке, вызываем метод Synchronize
end;
end;
dymka (2002-03-28 09:12:00) [12]код должен быть такой
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;
dymka (2002-03-28 09:09:00) [13]процедура переданная в методе Synchronize выполняется в КОНТЕКСТЕ ОСНОВНОГО ПОТОКА ПРИЛОЖЕНИЯ!
Весь код потока должен размещаться в теле Execute, либо вызываться без метода Synchronize!!! Это метод нужен для синхронизации твоего потока и основного потока, например обновление компонентов VCL итп..
Запускать поток нужно конструктором Create, где в качестве параметра передавать False, если поток нужно запустить немедленно, и True, если запустить его ты хочешь позже..
далее.. в теле Execute сделай следующее:
FreeOnTerminate := True; тогда при терминировании потока
он автоматически освободит свои ресурсы...
терминирую поток не вызовом Free, а вызовом метода Terminate,
Внутри потока используй проверку на терминирование - свойство Terminated...
gek (2002-03-28 09:08:00) [14]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
Виктор Щербаков (2002-03-28 09:06:00) [15]Всё правильно. Tmythread.MyProcedure будет выполняться в основном потоке т.к. ты используешь Synchronize.
MBo (2002-03-28 09:04:00) [16]Sinchronize надо те участки кода, которые обращаются к главному потоку.