TTaskクラスを使って並列プログラミング ~Delphiソースコード集
DelphiでTTaskクラスを使って並列プログラミングする方法を、素数判定のサンプルソースコードで解説します。
このサンプルソースコードでは100個のTTaskを使って100並列で素数判定を行います。
画面設計
Delphi IDEを起動し、「ファイル」⇒「Windows VCLアプリケーション -Delphi」をクリックしてプロジェクトと初期フォームを作成します。
右下ペインにある「パレット」から以下コンポーネントをドラッグ&ドロップします。
- TButton × 1個
- TMemo × 1個
ソースコードの記述
F12を押して コードエディタ に切り替えて以下のソースコードをコピペで記述します。
F12を押して フォームデザイナ に切り替えて、左下ペインのオブジェクトインスペクタで[イベント]タブを選択、Button1をクリックして選択し、
Button1.OnCreate に Button1Click を設定します。
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
System.Threading, System.SyncObjs, System.Math;
type
//並列プログラミング ライブラリの TTask を使用して
//Numが素数の場合はfAnswersに追加する
TPrimeTest=class(TTask, ITask)
private
fNum:INT64;
fAnswers:TStringList;
public
constructor Create(Num:Int64; Answers:TStringList);
procedure TaskStart;
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TPrimeTest }
constructor TPrimeTest.Create(Num: Int64; Answers: TStringList);
begin
//プライベート変数に保存する
fNum:=Num;
fAnswers:=Answers;
//親クラスのCreateを呼び出す
inherited Create(
nil, nil,
procedure
begin
Self.TaskStart;
end,
nil, nil, []
);
end;
procedure TPrimeTest.TaskStart;
var i,m:Int64;
flag:Boolean;
st:String;
begin
st:='';
if fNum<2 then
begin
exit;
end
else if (fNum=2) or (fNum=3) then
begin
st:=Format('%d は素数',[fNum]);
end
else
begin
m:=Trunc(Sqrt(fNum));
i:=2;
flag:=True;
while i<=m do
begin
if fNum Mod i =0 then
begin
flag:=False; //素数ではない
break;
end;
inc(i);
end;
if flag then
st:=Format('%d は素数',[fNum]);
end;
if st<>'' then
begin
//同時にオブジェクト使用しないように保護(ロック)する
System.MonitorEnter(fAnswers);
try
//配列を1個増やす
//SetLength(fAnswers.res,Length(fAnswers.res)+1);
//fAnswers.res[Length(fAnswers.res)-1]:=st;
fAnswers.Add(st);
finally
//保護(ロック)を解除する
System.MonitorExit(fAnswers);
end;
end;
end;
{TForm1}
procedure TForm1.Button1Click(Sender: TObject);
const
//最大100個のタスクを並列実行させる
MaxTaskCount:Integer = 100;
//10000から50000 の間にある素数を見つける
FromNumber:Integer=10000;
ToNumber :Integer=50000;
var i,n:Int64;
Tasks:TArray<ITask>;
TaskCount:Integer;
Answers:TStringList;
begin
Memo1.ScrollBars:=ssBoth;
Answers:=TStringList.Create;
try
n:=FromNumber;
while n<=ToNumber do
begin
if (n+MaxTaskCount-1)>ToNumber then
TaskCount:=ToNumber-n+1
else
TaskCount:=MaxTaskCount;
//並列処理用タスクを準備する
SetLength(Tasks,TaskCount);
for i := Low(Tasks) to High(Tasks) do
begin
Tasks[i]:=TPrimeTest.Create(n,Answers) as ITask;
inc(n);
end;
//全てのタスクの並列処理を開始する
for i := Low(Tasks) to High(Tasks) do Tasks[i].Start;
//全てのタスクが完了するまで待つ
//タスクが開始する順序と終了する順序は保証されない
TTask.WaitForAll(Tasks);
end;
//Memo1.Lines.BeginUpdate;
Memo1.Lines.Assign(Answers);
//Memo1.Lines.EndUpdate;
finally
Answers.Free;
end;
end;
end.
実行する
IDEの実行ボタンをクリックして実行します。
Button1をクリックすると、10000から50000までの間にある素数をMemo1に表示します。
