Программирование помогает решать различные задачи. Но чтобы научиться чему-то и это понять, часто нужно решать трудные задачи. Программирование и обучение программированию очень часто занимает слишком много времени.
Иногда человеку нужно увидеть максимально простой код для разбора, чтобы код разобрать и научиться его использовать.
Один из таких этапов - Проргаммирование и используемые в нем потоки.
Потоки используют для выполнения псевдопаралельных процессов. Это если в одну единицу времени нужно выполнять различные задачи.
(Например, одновременная загрузка содержимого из двух очень больших файлов в 2 компонента TMemo)
Я решил показать максимально простой примитив, на который оказался способен. Я не буду загружать файлы, а использую 2 компонента TProgressBar и одну кнопку TButton
(для тех кто в танке - Button - Вкладка Standart - ProgressBar - вкладка Win32)
Моя программа будет написана только в одном окне Unit1 и паралельно загружать оба ProgressBar а.
Так сделано потомучто статья содержит ознакомительный контент и должна дать понять как использовать потоки.
Подготавливаем форму
Помещаем 2 компонента ProgressBar на нашу форму. Делаем их одинаковых размеров.
- Помещаем 1 кнопку Button на форму
- Нажимаем ctrl+F12 (либо View -> Units)
Приступаем к написанию кода. Начинаем программирование и создаем свои потоки))
Для удобства воспринятия следующего кода добавим одну константу.
const N=12000; - Это будет константа для расширения положений ползунка.
========================================================
Определяем новый класс и определяем ему тип Потоки (TThread)
Type
MyThread = class(TThread)
end;
Написать это нужно сразу после определения типа TForm (начинается Type Form=class(TForm) - заканчивается оператором end; )
Наши потоки будут использовать 2 ProgressBar, значит создадим 2 процедуры. Это те 2 процедуры, которые должны выполняться параллеьно. Вписываем их перед словом Private.
Button1: TButton;
procedure _1;
procedure _2;
private
Когда написали эти процедуры - можно нажать ctrl+shift+C - в наш код, в нужные места должны поставиться такие строчки:
procedure TForm1._1;
begin
end;
procedure TForm1._2;
begin
end;
Сюда мы впишем наш код. Первая процедура - увеличивает ползунок Первого ProgressBar,
вторая ползунок второго
procedure TForm1._1;
begin
ProgressBar1.Position:=ProgressBar1.Position+1; //Смещаем ползунок
end;
procedure TForm1._2;
begin
ProgressBar1.Position:=ProgressBar1.Position+1;;//Смещаем ползунок
end;
- Так мы написали 2 отдельно выполняемых фрагмента кода. Теперь нужно знать как их вызвать и заставить работать в параллельном режиме, другими словами - это наши потоки. Если сейчас выполнить программу - то загрузится форма и ничего не произойдет.
Добавляем к нашему классу потоки (NewThread) новую процедуру.
Type
NewThread = class(TThread)
protected
procedure execute;override;
end;
Нажимаем Ctrl+shift+C - в код должны вставиться такое:
procedure NewThread.execute;
begin
inherited;
end;
Это та процедура, которая будет отвечать за то, что наши потоки будут выполняться параллельно. С помощью неё мы и будем потоки эти синхронизировать. Для синхронизации добавляем новую переменную в кусок кода (делаем её видимой)
Type
NewThread = class(TThread)
protected
procedure execute;override;
public
W:Boolean
end;
Теперь пишем сам кусок кода, синхронизирующий потоки. Для этого в кусок кода, отвечающий за синхронизаци пишем:
procedure NewThread.execute;
begin
inherited;
While (Form1.ProgressBar1.Position<N) or (Form1.ProgressBar2.Position<N) do Begin
if W=true then Synchronize(Form1._1)
else Synchronize(Form1._2);
end;
end;
Это один из методов синхронизации, он годится только для простых проектов. Осталось только его вызвать. Вызывать наши потоки, мы будем нажатием на кнопку. Для этого переходим на форму (Shift+F12 или view-Forms) и делаем двойной клик на кнопке. Должна появиться новая процедура.
procedure TForm1.Button1Click(Sender: TObject);
begin
end;
Добавляем 2 переменные, соответствующие потокам
procedure TForm1.Button1Click(Sender: TObject);
var P1,P2:NewThread;
begin
end;
Теперь пишем самый главный код - Инициализируем и запускаем наши потоки.
procedure TForm1.Button1Click(Sender: TObject);
var P1,P2:NewThread;
begin
P1:=NewThread.Create(true); P2:=NewThreadCreate(true); //Инициализировали потоки
P1.W:=true;P2.W:=false; // Установили значения для проверки
{Установили приоритеты выполнения}
P1.Priority:=tplowest;
P1.Priority:=tphighest;
P1.Resume; P2.Resume; (Продолжаем выполнение потоков)
end;
Все, потоки готовы, но есть маленький момент. Чтобы они не подвесили программу наподобии бесконечного цикла, мы должны их перевести в спящее положение. У нас, в нашем примере это сделать очень просто. Можно, например, в обоих процедурах указать условие, что если Ползунок достигает конца, то перейти в бездействие.
procedure TForm1._1;
begin
if ProgressBar1.Position<Form1.ProgressBar1.Position then ProgressBar1.Position:=ProgressBar1.Position+1;
end;
procedure TForm1._2;
begin
if ProgressBar2.Position<Form1.ProgressBar2.Position then ProgressBar2.Position:=ProgressBar2.Position+1;
end;
==================================================
Код программы:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;
type
TForm1 = class(TForm)
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
Button1: TButton;
procedure _1;
procedure _2;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Type
NewThread = class(TThread)
protected
procedure execute;override;
public W:boolean;
end;
var
Form1: TForm1;
i:Integer;
const N=12000;
implementation
{$R *.dfm}
{ NewThread }
{ TForm1 }
procedure TForm1._1;
begin
if ProgressBar1.Position<N then ProgressBar1.Position:=ProgressBar1.Position+1;
end;
procedure TForm1._2;
begin
if ProgressBar2.Position<N then ProgressBar2.Position:=ProgressBar2.Position+1;
end;
{ NewThread }
procedure NewThread.execute;
begin
inherited;
While (Form1.ProgressBar1.Position<N) or (Form1.ProgressBar2.Position<N) do Begin
if W=true then Synchronize(Form1._1)
else Synchronize(Form1._2);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var P1,P2:NewThread;
begin
ProgressBar1.Max:=N;
ProgressBar2.Max:=N;
P1:=NewThread.Create(true);
P2:=NewThread.Create(true);
P1.W:=true;
P2.W:=false;
P1.Priority:=tplowest;
P2.Priority:=tphighest;
P1.Resume;
P2.Resume;
end;
end.
Комментариев нет:
Отправить комментарий