In Delphi mit Omni Thread Library asynchron ein Funktionsergebnis erhalten
Ich versuche, eine Funktion von einer anderen Unit / Klasse aufzurufen, deren Ausführung einige Zeit in Anspruch nimmt und die einen String-Wert zurückgibt. Ich konnte keine gute Referenz finden, die C # async-await ähnelt, wie ein einfacher Ansatz in Delphi. Die Verwendung der Omni Thread-Bibliothek scheint mir eine gute Idee zu sein.
in einfaches Beispiel ist ein guter Anfang für mic
Beispielansatz:
procedure TForm1.button1Click(Sender: TObject);
begin
// notify before starting the task
memo1.Lines.Add('calling a asynchronous function..');
// call to the function that takes some time and returns a string value
memo1.Lines.Add(GetMagicString);
// notify that the task has been completed
memo1.Lines.Add('Results fetched successfully.');
end;
Hier ist die Funktion GetMagicString sollte das Ergebnis asynchron verarbeiten. Sobald das Ergebnis vorliegt, sollte das Programm erst dann mitteilen, dass die Aufgabe abgeschlossen wurde. Ich benutze übrigens Delphi-XE.
Edit1: Hier ist was ich ausprobiert habe. Aber ich bin immer noch nicht in der Lage, den richtigen Weg zu finden, um die Arbeit zu erledigen. Das Problem ist, wie der Wert zurückgegeben wird.
.....
private
ResultValue: IOmniFuture<string>;
.........
.....
function TForm1.FutureGet: string;
begin
Sleep(3000);
Result := 'my sample magic string response ' + IntToStr(Random(9999));
end;
procedure TForm1.FutureGetTerminated;
begin
// This code fired when the task is completed
memo1.Lines.Add(ResultValue.Value);
end;
function TForm1.GetMagicString: string;
begin
ResultValue := Parallel.Future<string>(FutureGet,
Parallel.TaskConfig.OnTerminated(FutureGetTerminated));
end;
Hier wird Result: = ResultValue.Value verwendet, um die Benutzeroberfläche auszublenden.
Edit2
Ich habe Änderungen gemäß der angegebenen Antwort vorgenommen.
MainForm Code: unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Unit2;
type
TForm1 = class(TForm)
memo1: TMemo;
button1: TButton;
procedure button1Click(Sender: TObject);
private
FOnStringReceived: TMyEvent;
procedure StringReceived(const AValue: string);
property OnStringReceived: TMyEvent read FOnStringReceived write FOnStringReceived;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.button1Click(Sender: TObject);
var
MyObject: TMyClass;
begin
// notify before starting the task
memo1.Lines.Add('calling a asynchronous function..');
// call to the function that takes some time and returns a string value
MyObject := TMyClass.Create;
OnStringReceived := StringReceived;
try
MyObject.GetMagicStringInBackground(OnStringReceived);
finally
MyObject.Free;
end;
end;
procedure TForm1.StringReceived(const AValue: string);
begin
memo1.Lines.Add(AValue);
// notify that the task has been completed
memo1.Lines.Add('Results fetched successfully.');
end;
end.
Other Unit Code: unit Unit2;
interface
uses SysUtils, OtlTask, OtlParallel, OtlTaskControl;
type
TMyEvent = procedure(const aValue: string) of object;
type
TMyClass = class
private
FOnStringReceived: TMyEvent;
function GetMagicString: string;
public
procedure GetMagicStringInBackground(AEvent: TMyEvent);
end;
implementation
{ TMyClass }
function TMyClass.GetMagicString: string;
begin
Sleep(3000);
Result := 'my sample magic string response ' + IntToStr(Random(9999));
end;
procedure TMyClass.GetMagicStringInBackground(AEvent: TMyEvent);
var
theFunctionResult: string;
begin
Parallel.Async(
procedure
begin
theFunctionResult := GetMagicString;
end,
Parallel.TaskConfig.OnTerminated(
procedure (const task: IOmniTaskControl)
begin
if Assigned(AEvent) then
AEvent(theFunctionResult);
end)
);
end;
end.
Ja, der Code funktioniert wie erwartet. Ich möchte nur wissen, ob dies der beste Weg ist, das zu tun, was ich wirklich tun möchte.