我想從另一個單元/類調用一個函數,這將需要一些時間來執行任務並返回一個字符串值。在Delphi中我找不到像C#異步等待類似的簡單方法。使用Omni線程庫對我來說似乎是個好主意。使用Omni線程庫在Delphi中異步獲取函數結果
一個簡單的例子對我來說是一個很好的開始。
樣品的方法:
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;
這裏,函數GetMagicString應異步處理的結果。一旦獲得結果,只有程序應該通知任務已完成。順便說一下,我正在使用Delphi-XE。
編輯1: 這是我試過的。但我仍然無法找出完成工作的正確方法。問題是如何返回值。
.....
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;
這裏,使用Result:= ResultValue.Value會減少UI。
EDIT2
我所做的更改按照所提供的答案。
MainForm代碼: 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.
其他單位代碼: 單位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.
是的,代碼正常工作。我只想知道這是做我真正想做的最好的方式。
這並不是所有的異步 –
http://www.thedelphigeek.com/2011/04/simple-background-tasks-with.html – TLama
@DavidHeffernan是的,這根本不是異步。其實,這是我想要實現的方法。我編輯了這個問題。請hava熟悉它。 –