Hello,
My question is similar to this one
http://otl.17slon.com/forum/index.php/topic,302.0.html, but a little more elaborated:
I am in the process of evaluation the library and I have one concern - passing parameters.
Here is example which I've prepared and would like to discuss.
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TGlobalStructure = record
X,Y,Z: Integer;
end;
type
TForm42 = class(TForm)
btnOTL: TButton;
btnStandardThread: TButton;
procedure btnOTLClick(Sender: TObject);
procedure btnStandardThreadClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
GlobalStructure: TGlobalStructure;
procedure GetThreadResult(Sender: TObject);
procedure OTLAddNumbers;
end;
type
TAddingThread = class(TThread)
protected
procedure Execute; override;
public
X,Y,Z: Integer;
end;
function AddNumbers(const X, Y: Integer): Integer;
var
Form42: TForm42;
implementation
uses
OtlTaskControl, OtlParallel;
{$R *.dfm}
function AddNumbers(const X, Y: Integer): Integer;
begin
Result := X + Y;
end;
procedure TForm42.btnOTLClick(Sender: TObject);
begin
//First I must initialize global structure which is quite inconvenient
//becasue I have to take care of that structure during executing of the thread.
//I must watch out for it, not to modify it by accident, etc.
GlobalStructure.X := 1;
GlobalStructure.Y := 2;
Parallel.Async(
OTLAddNumbers,
Parallel.TaskConfig.OnTerminated(
procedure (const task: IOmniTaskControl)
begin
// executed in main thread
ShowMessage(IntToStr(GlobalStructure.Z));
end
)
);
end;
procedure TForm42.btnStandardThreadClick(Sender: TObject);
var
AddingThread: TAddingThread;
begin
//In the case of normal thread I do not have to worry about existance of
//variables after running the thread because they are copied into the thread object.
AddingThread := TAddingThread.Create(True);
AddingThread.FreeOnTerminate := True;
AddingThread.OnTerminate := GetThreadResult;
AddingThread.X := 1;
AddingThread.Y := 2;
AddingThread.Resume;
end;
procedure TForm42.GetThreadResult(Sender: TObject);
begin
ShowMessage(IntToStr(TAddingThread(Sender).Z));
end;
procedure TForm42.OTLAddNumbers;
begin
//Passing variables via globals is ugly...
GlobalStructure.Z := AddNumbers(GlobalStructure.X, GlobalStructure.Y);
end;
{ TAddingThread }
procedure TAddingThread.Execute;
begin
Z := AddNumbers(X,Y);
end;
end.
In the above example I am comparing standard TThread approach to OTL approach. IMHO the problem with Async approach is passing parameters to underlying procedure via some global variables. I think this is quite unsafe and decreases readability of code.
I could solve that problem by writting a class which takes up the parameters and then executes Async, but that class would be a wrapper for Async which on its own is wrapper for TThread...
What design pattern would you suggest that in your opinion is best for solving this problem? How do you solve this problem within your programs?
Thanks for the answer,
regards.