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

而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. dshow采集过程

    捕捉静态图片常用的filter是Sample Graber filter,它的用法参考手册.然后将捕捉filter的静态PIN连接到Sample Grabber,再将Sample Grabber连接到 ...

  2. Python基本数据类型以及字符串

    基本数据类型                数字  int ,所有的功能,都放在int里            a1 = 123            a1 = 456                 ...

  3. ubuntu oracle 环境搭建

    安装 Oracle SQL Developer Oracle客户端安装 https://oracle.github.io/odpi/doc/installation.html#linux

  4. Delphi TQuery 的Locate用法

    Help里的解释 function Locate(const KeyFields: String; const KeyValues: Variant; Options: TLocateOptions) ...

  5. angular指令的compile,prelink 和 postlink以及controller

    一. 指令模板选项有complie和link两个字段,两者之间存在如下关系: 当compile字段存在时,link字段将被忽略,compile函数的返回值将作为link字段. 当compile不存在, ...

  6. zabbix监控haproxy

    首先修改haproxy.cfg listen monitor_stat : stats uri /ihaproxy-stats stats realm Haproxy\ Statistics stat ...

  7. Linux安装卸载jdk1.8

    首先到官网下载  Linux x64 182.87 MB jdk-8u191-linux-x64.tar.gz https://www.oracle.com/technetwork/java/java ...

  8. linux mce的一些相关内容和用户态监控的设计方法

    之所以想起写一点关于mce的东西,倒不是因为遇到mce的异常了,之前遇到过很多mce的异常,内存居多,但没有好好记录下来,写这个是因为参加2018 clk南京会议的一点想法. void __init ...

  9. ReactiveX 学习笔记(2)创建数据流

    操作符(Operators) Rx 的操作符能够操作(创建/转换/组合) Observable. Creating Observables 本文主题为创建/生成 Observable 的操作符. 这里 ...

  10. 18.4 运行脚本 sudo ./launcher.sh 必须先给他权限 才能使用

    我们发现我们每次启动服务都要打一大堆命令,ng build --watch ,nodemon server.js ,等等 凡是重复的工作,我们要可以代码完成 要想运行它呢 你必须将你运行的上述(脚本中 ...