На этом шаге мы рассмотрим приложение,
в котором демонстрируется работа потоков с разными приоритетами.
На форму следует поместить шесть компонетнов TLabel и два компонента TButton. Вид формы представлен на рис. 1.
Рис.1. Вид формы приложения
Проект содержит два модуля. Текст модуля Main.
unit Main; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, MyThread; type TForm1 = class(TForm) Label1: TLabel; Button1: TButton; Button2: TButton; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } co1:TCountObj1; co2:TCountObj2; co3:TCountObj3; public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); begin //создаем объекты потоков co1:=TCountObj1.Create(true); co2:=TCountObj2.Create(true); co3:=TCountObj3.Create(true); //назначаем приорететы потокам co1.Priority:=tpIdle; co2.Priority:=tpLower; co3.Priority:=tpNormal; //запускаем потоки co1.Resume; co2.Resume; co3.Resume; end; procedure TForm1.Button2Click(Sender: TObject); begin //уничтожаем потоки co1.Terminate; co2.Terminate; co3.Terminate; end; end.
Текст модуля MyThread.
unit MyThread; interface uses Classes, Sysutils; type TCountObj1 = class(TThread) private { Private declarations } index:Integer; procedure UpdateLabel; protected procedure Execute; override; end; type TCountObj2 = class(TThread) private { Private declarations } index:Integer; procedure UpdateLabel; protected procedure Execute; override; end; type TCountObj3 = class(TThread) private { Private declarations } index:Integer; procedure UpdateLabel; protected procedure Execute; override; end; implementation uses Main; { TCountObj1 } procedure TCountObj1.Execute; begin index:=1; while index>0 do begin Synchronize(UpdateLabel); Inc(index); if index>100000 then index:=0; if terminated then exit; end; end; procedure TCountObj1.UpdateLabel; begin Form1.Label1.Caption:=IntToStr(Index); end; { TCountObj2 } procedure TCountObj2.Execute; begin index:=1; while index>0 do begin Synchronize(UpdateLabel); Inc(index); if index>100000 then index:=0; if terminated then exit; end; end; procedure TCountObj2.UpdateLabel; begin Form1.Label2.Caption:=IntToStr(Index); end; { TCountObj3 } procedure TCountObj3.Execute; begin index:=1; while index>0 do begin Synchronize(UpdateLabel); Inc(index); if index>100000 then index:=0; if terminated then exit; end; end; procedure TCountObj3.UpdateLabel; begin Form1.Label3.Caption:=IntToStr(Index); end; end.
Разберем принцип работы данной программы. После нажатия кнопки "Запустить" создаются и запускаются три потока с разными приоритетами. Для запуска можно обойтись без использования метода Resume, если передавать в метод Create параметром значение False. Далее потоки начинают параллельную работу: каждый поток увеличивает свой собственный счетчик. После нажатия кнопки "Остановить" для каждого потока произойдет вызов метода Terminate, и потоки будут уничтожены. Наглядность работы программы будет зависеть от тактовой частоты процессора: чем она выше, тем быстрее будет происходить увеличение счетчика. При слишком быстром изменении значений, можно увеличить значение, при достижении которого обнуляется счетчик, тогда работа программы будет более наглядной.
Текст этого примера можно взять здесь.
На следующем шаге мы рассмотрим, как с помощью потоков можно выполнять фоновые процедуры.