Search
Write a publication
Pull to refresh

Многопоточность Delphi

Если требуется выполнить операции в фоновом режиме или любую обработку, не связанную напрямую c пользовательcким интерфейсом, можно воспользоваться следующим подходом: внутри основного процесса порождать подпроцесс в виде отдельного потока выполнения. Программирование многопоточноcти может показаться неясным вопросом. Но на самом деле это не так сложно, даже если вы подходите к нему c осторожностью.
RТL-библиотека Delphi предоставляет класс TThread, позволяющий создавать потоки и управлять ими. Этот класс никогда не используется непосредственно, поскольку он является абстрактным классом, то есть классом c виртуальными абстрактными методами. Для использования потоков всегда создаются подклассы класса TThread и применяются возможности базового класса.

Класс TThread имеет конструктор с единственным параметром (CreateSuspended), определяющий, будет ли поток запускаться немедленно либо будет отложен на потом. Если объект поток стартует непосредственно либо возобновляется, он запускает метод Execute и ожидает его выполнения. Класс предоставляет защищенный интерфейс, включающий два ключевых метода для подклассов-потоков:
procedure Execute; virtual; abstract;
procedure synchronize(Method: TThreadMethod);

Метод Execute, объявленный в качестве виртуальной абстрактной процедуры, должен быть переопределен в каждом поточном классе. Он содержит основной код потока — код, который при использовании системной функции обычно помещается в поточную функцию (TThread function).
Метод Synchronize предназначен для предотвращения параллельного доступа к VCL- компонентам. VСL-код выполняется внутри основного потокa программы, поэтому во избежание проблемы повторного входа и параллельного доступа к совместно используемым ресурсам необходимо синхронизировать доступ к VCL. Единственным параметром метода Synchronize является метод, не принимающий никаких параметров; обычно метод того же поточного класса. Поскольку этому методу ненозможно передать параметры, он является общим для хранения некоторых значений в данных объекта-потока в методе Execute и использования этих данных в синхронизированных методах.

Пример организации поточной обработки
В кaчестве пpимеpa потока обратимся к следующему примеру. Этот пример порождает вторичный поток для вычисления суммы простых чисел. Класс- поток имеет обычный метод Execute, начальное значение, передаваемое в public-свойство Max, и два внутренних значения(FTotal и FPosition), используемых для синхронизации выходных значений в методах ShowTotal и UpdateProgress. Ниже представлено полное обьявление класса для пользовательского обьекта-потока

type TPrimeAdder=class(TThread)
private
FMax,FTotal, FPosition:Integer;
protected
procedure Execute;override;
procedure ShowTotal;
procedure UpdateProgress;
public
property Max:Integer read FMax write FMax;
end;


А вот описание методов, созданного нами класса:

procedure TPrimeAdder.Execute;
var I,Tot: Integer;
begin
Tot:=0;
for i:=1 to FMax do
begin
if IsPrime(I) then // Функция IsPrime() проверяет является ли число простым
Tot:=Tot+I;
FPosition:= I*100 div FMax;
Synchronize(UpdateProgress);
end;
FTotal:=Tot;
Synchronize(Showtotal);
end;

procedure TPrimeAdder.ShowTotal;
begin
ShowMessage('Thread ' +Inttostr(FTotal));
end;

procedure TPrimeAdder.UpdateProgress;
begin
Form1.ProgressBar1.Position:=FPosition;
end;


Наш обьект-поток создается при щелчке на кнопке и автоматически уничтожается, когда завершается выполнение метода Execute:

procedure TForm1.Button1Click(Sender:TObject);
var OurThread:TPrimeAdder;
begin
OurThread:=TPrimeAdder.Create(true);
OurThread.Max:=StrToint(Edit1.text);
OurThread.FreeOnTerminate:=True;
OurThread.Resume;
end;


И напоследок скриншот программки.

image
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.