异步编程,是项目中非常有用的而且常用的一种方法,大多以线程实现。
而Delphi传统方法使用线程略为烦琐,好在其后续版本中,提供一些方法,简化一些操作。
几个概念:
匿名线程:TAnonymousThread,Delphi XE始支持。
匿名方法:reference to procedure|function,Delphi 2009 始支持。
匿名线程
其实只是创建一个线程,传入一匿名方法并执行,实现倒也简单,我就移其入Dephi 2009中。其实义如下:
TAnonymousThread = class(TThread)
private
FProc: TProc;
protected
procedure Execute; override;
public
constructor Create(const AProc: TProc);
end;
{ TAnonymousThread }
constructor TAnonymousThread.Create(const AProc: TProc);
begin
inherited Create(True);
FreeOnTerminate := True;
FProc := AProc;
end;
procedure TAnonymousThread.Execute;
begin
FProc();
end;
这样,使用简单的多线程,就不必再继承TThread类创建自己线程去工作了。其参数TProc,即为一匿名方法。
而在TThread类中,定义一类方法直接创建,其方法为:
// CreateAnonymousThread will create an instance of an internally derived TThread that simply will call the
// anonymous method of type TProc. This thread is created as suspended, so you should call the Start method
// to make the thread run. The thread is also marked as FreeOnTerminate, so you should not touch the returned
// instance after calling Start as it could have run and is then freed before another external calls or
// operations on the instance are attempted.
class function CreateAnonymousThread(const ThreadProc: TProc): TThread; static;
class function TThread.CreateAnonymousThread(const ThreadProc: TProc): TThread;
begin
Result := TAnonymousThread.Create(ThreadProc);
end;
由此可见,一行代码即可实现简单的线程操作。
匿名方法
自定义匿名方法,正式语法为:
type
TFun = reference to function(const num: Integer): Integer;
procedure也是一样。但在SysUtils单元中,已内置一些预定义类型并且支持泛型,可直接拿来用,如下所示:
// Generic Anonymous method declarations
type
TProc = reference to procedure;
TProc<T> = reference to procedure (Arg1: T);
TProc<T1,T2> = reference to procedure (Arg1: T1; Arg2: T2);
TProc<T1,T2,T3> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3);
TProc<T1,T2,T3,T4> = reference to procedure (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4);
TFunc<TResult> = reference to function: TResult;
TFunc<T,TResult> = reference to function (Arg1: T): TResult;
TFunc<T1,T2,TResult> = reference to function (Arg1: T1; Arg2: T2): TResult;
TFunc<T1,T2,T3,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3): TResult;
TFunc<T1,T2,T3,T4,TResult> = reference to function (Arg1: T1; Arg2: T2; Arg3: T3; Arg4: T4): TResult;
TPredicate<T> = reference to function (Arg1: T): Boolean;
我是喜欢懒省事的,有已有的即不再自写,上面诸多类型,已能应对大多数使用场景了。
需要注意的是TFunc使用方法,因为它有返回值。比如TFunc<Integer, Interger>就与TFun实现原理一样。
可验证如下代码:
procedure TfrmMain.FormCreate(Sender: TObject);
var
f1: TFun;
f2: TFunc<Integer, string>;
begin
f1 := function (const num: Integer): Integer
begin
Result := num * num;
end;
OutputDebugString(PChar('f1(9) = ' + IntToStr(f1(9)))); //Debug output: f1(9) = 81
f2 := function (num: Integer): string
begin
Result := IntToStr(num * num);
end;
OutputDebugString(PChar('f2(9) = ' + f2(9))); //Debug output: f2(9) = 81
end;
由此可延伸开来,匿名线程与匿名方法结合,可简单的执行并行操作,举例如下:
procedure TfrmMain.btnStartClick(Sender: TObject);
begin
Edit1.Text := 'start...';
TThread.CreateAnonymousThread(
procedure
var
i: Integer;
begin
Sleep(3000);
for i := 0 to 99999 do
TThread.Synchronize(nil,
procedure
begin
Edit1.Text := IntToStr(i);
end
);
Edit1.Text := 'end.'; //此处亦要同步,懒省事没整Synchornize
end
).Start;
end;
创建一匿名线程,传以匿名方法,并同步主线程显示,工作正常。相比c#之{}来说,begin..end的确看起业不像话。
多省事,是不是?
参考资料:
Delphi 2009 中的匿名方法(reference to)
来源:oschina
链接:https://my.oschina.net/u/4361539/blog/3857303