异步编程,是项目中非常有用的而且常用的一种方法,大多以线程实现。

而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()))); //Debug output: f1(9) = 81 f2 := function (num: Integer): string
begin
Result := IntToStr(num * num);
end;
OutputDebugString(PChar('f2(9) = ' + f2())); //Debug output: f2(9) = 81
end;

由此可延伸开来,匿名线程与匿名方法结合,可简单的执行并行操作,举例如下:

procedure TfrmMain.btnStartClick(Sender: TObject);
begin
Edit1.Text := 'start...';
TThread.CreateAnonymousThread(
procedure
var
i: Integer;
begin
Sleep();
for i := to do
TThread.Synchronize(nil,
procedure
begin
Edit1.Text := IntToStr(i);
end
);
Edit1.Text := 'end.'; //此处亦要同步,懒省事没整Synchornize
end
).Start;
end;

创建一匿名线程,传以匿名方法,并同步主线程显示,工作正常。相比c#之{}来说,begin..end的确看起业不像话。

多省事,是不是?

参考资料:

Anonymous Methods in Delphi

现在, Delphi 的多线程已经非常易用了!

Delphi 2009 中的匿名方法(reference to)

Delphi异步编程:匿名线程与匿名方法的更多相关文章

  1. C#:异步编程和线程的使用(.NET 4.5 )

    摘自:http://www.codeproject.com/Articles/996857/Asynchronous-programming-and-Threading-in-Csharp-N(葡萄城 ...

  2. 异步编程和线程的使用(.NET 4.5 )

    C#:异步编程和线程的使用(.NET 4.5 )   异步编程和线程处理是并发或并行编程非常重要的功能特征.为了实现异步编程,可使用线程也可以不用.将异步与线程同时讲,将有助于我们更好的理解它们的特征 ...

  3. C#:异步编程和线程的使用(.NET 4.5 ),异步方法改为同步执行

    摘自:http://www.codeproject.com/Articles/996857/Asynchronous-programming-and-Threading-in-Csharp-N(葡萄城 ...

  4. ES6 --- JS异步编程的几种解决方法及其优缺点

    导言: 我们都知道 JS 是单线程的,这也正是异步编程对于 JS  很重要的原因,因为它无法忍受耗时太长的操作.正因如此有一系列的实现异步的方法. 方法一  setTimeout 常用于:定时器,动画 ...

  5. C#5.0 异步编程 Async和Await--异步方法的规范和注意事项

    要些异步方法要注意一下几点: 异步方法的返回值有三种: 1.没有任何返回值的void 2.返回一个Task任务的Task,可以获得该异步方法的执行状态 3.返回Task<T> 可以获得异步 ...

  6. 廖雪峰Java11多线程编程-2线程同步-2synchronized方法

    1.Java使用synchronized对一个方法进行加锁 class Counter{ int count = 0; public synchronized void add(int n){ cou ...

  7. JUC 并发编程--08,线程池,三大方法,七大参数,4种拒绝策略,代码演示

    三大方法: //线程池核心线程数为n, 最大线程数为 n ExecutorService fixedThreadPool = Executors.newFixedThreadPool(n); 源码: ...

  8. C#异步编程の----Threadpool( 线程池)

    简介: 一个托管线程的创建需要数千个CPU周期,并且当发生线程切换时也会带来明显的开销.考虑线程的重用,避免不断重复创建新的线程是提高系统效率的一种方式. 线程池是一种提供效率的方式,它创建好一些线程 ...

  9. 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

随机推荐

  1. Django--ORM(模型层)--多表(重重点)

    一.数据库表关系 单表 重复的字段太多,所以需要一对多,多对多来简化 多表 多对一 多对多 一对一 =============================================== 一对 ...

  2. php 分页实现 和 php 大文件上传失败的处理方式

    1. php分页: 要想做php的分页,首先要弄清楚要什么样的分页,关系到哪些参数,参数之间怎么关联: 目标分页效果如下: 分析: 1.主要涉及两个参数:一个是当前输出页面的页码,用变量$p 表示,另 ...

  3. 对于两个初始时设置为Sensor的刚体,不会触发preSolve和postSolve

    Main.as package{ import Box2D.Common.Math.b2Vec2; import Box2D.Dynamics.b2Body; import Box2D.Dynamic ...

  4. C++中类的多继承

    在写这一主题的文章之前,在网上找到一篇很非常好的文章C++之继承与多态.就没有必要做重复造轮子的事件了,那就从这篇文章开始吧! 在c++中一个类可以从多个基类中派生(即可以有多个父类),这就是多继承. ...

  5. avalon1与avalon2的异同点

    avalon2并不向下兼容avalon1,但许多API与指令很相似,迁移成本比较低.此外,良好的性能与强大的功能是你迁移的动力.下面是一个列表,如有提问尽管提出. avalon1与avalon2的异同 ...

  6. 一个简单的dropdown(CSS+jquery)

    by 司徒正美 .dropdown{ position: relative; } .dropdown div{ position: relative; width:200px; height:30px ...

  7. linux目录结构详解(以suse linux 10为例)

    一.文件系统结构 位于Linux系统的最顶端即根目录是/.Linux的文件系统的入口就是/,所有的目录.文件.设备都在/之下,/就是Linux文件系统的组织者,也是最上级的领导者. 它之下的子目录有: ...

  8. Javascript中call、apply之我见

    一.call和apply定义. 1.Call 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 参数 thisObj 可选项.将被用作当前对象的对象. arg ...

  9. 简单自定义UIToolBar

    let item1 = UIBarButtonItem(title: "分享", style: .Plain, target: self, action: nil) let ite ...

  10. spring 中AOP的基本知识点

    首先AOP就是一个动态代理,主要运用在事务控制,日志记录,安全控制等方面 1.连接点(Joinpoint):一个连接点 总是 代表一个方法的执行. 2.切入点(Pointcut):匹配连接点的 表达式 ...