Сама идея:
Запустит несколько паралельных потоков для выполнения некой общей задачи, причем каждый поток должен получить свои параметры для работы.
Применение на будущее: например одновременно сканирование файлов в нескольких директориях, понятно что имя директории для сканирования для каждого потока должно быть свое. Хоть и алгоритм сканирования общий.
Демо: передача параметров через блокирующую коллекцию, использование параметров через record (обертка), передаются два параметра частота и длительность, функция выполняющаяся в потоке получает эти параметры и 10 раз проигрывает сигнал с такой частотой и длительностью.
Потоков на запуск 4, работают одновременно 2....
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
OTLParallel, OtlTaskControl, OtlCollections, OtlCommon;
type
TParametersForProc = record
Hz : Integer;
Duration : Integer;
end;
TForm3 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
Join : IOmniParallelJoin;
CollectionParams : IOmniBlockingCollection;
public
{ Public declarations }
procedure JoinProcExecute;
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure Go(Hz, Duration : Integer);
var
I: Integer;
begin
for I := 0 to 10 do
begin
Sleep(1000);
Winapi.Windows.Beep(Hz, Duration);
end
end;
procedure TForm3.JoinProcExecute;
var
Value : TOmniValue;
ParamProc : TParametersForProc;
begin
// Взять из коллекции параметры
CollectionParams.Take(Value);
// Преобразовать обратно
ParamProc := Value.Unwrap;
// Запустить процедуру с переданными параметрами
Go(ParamProc.Hz, ParamProc.Duration);
// вывести параметры
Memo1.Lines.Add(Format('Hz : %d; duration: %d',[ParamProc.Hz, ParamProc.Duration]));
end;
procedure TForm3.Button1Click(Sender: TObject);
var
arrayProc : array of TProc;
I: Integer;
Value : TOmniValue;
ParamProc : TParametersForProc;
begin
CollectionParams := TOmniBlockingCollection.Create;
SetLength(arrayProc, 4);
for I := Low(arrayProc) to High(arrayProc) do
begin
// Для каждого потока свои параметры, поэтому перед запуском потоков
// в коллекцию добавляем параметры, функция выполняющаяся в потоке будет
// брать параметр для себя из коллекции
ParamProc.Hz := (I+1) * 1000;
ParamProc.Duration := (I+1) * 20;
// обернуть рекорд к TOmniValue
Value := TOmniValue.Wrap(ParamProc);
// Добавим в параметры
CollectionParams.Add(Value);
arrayProc[i] := JoinProcExecute;
end;
CollectionParams.CompleteAdding; // добавление завершено
// NumTasks(2) - два потока выполняются одновременно
Join := Parallel.Join(arrayProc).NumTasks(2).NoWait.Execute; // запуск параллельных потоков
end;
end.