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

而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. SQL之to_date()以及关于日期处理的详解

    日期例子: SELECT TO_DATE('2006-05-01 19:25:34', 'YYYY-MM-DD HH24:MI:SS') FROM DUAL SELECT TO_DATE('2006- ...

  2. C++复习:C++的类型转换

    C++的类型转换 1 类型转换名称和语法 C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a C++风格的类型转换提供了4种类型转换操作符来 ...

  3. Bash:精华

    # 声明索引数组(以从0开始的整数做索引的数组).以下三种等效. declare -a array declare array=(this is numeric array ) array=(this ...

  4. 从初始化列表和构造函数谈C++的初始化机制

    来源:http://blog.csdn.net/theprinceofelf/article/details/20057359 前段时间被人问及“初始化列表和构造有什么区别?”我竟一时语塞,只好回头 ...

  5. android apk 在哪个目录下安装?

    system/app系统自带的应用程序,无法删除.data/app用户程序安装的目录,有删除权限.安装时把apk文件复制到此目录.data/data存放应用程序的数据

  6. Ajax核心技术代码

    /* @author weichen */ var xhr = ''; function Ajax() { if(window.XMLHttpRequest) { var xhr = new XMLH ...

  7. TLS协议工作过程;如何应用TLS/SSL协议为WEB流量提供安全

      SSL/TLS协议的基本过程是这样的: 客户端向服务器端索要并验证公钥. 双方协商生成"对话密钥". 双方采用"对话密钥"进行加密通信.   上面过程的前两 ...

  8. Git设置/取消代理

    设置代理 git config --global http.proxy http://proxy.com:1234 git config --global https.proxy http://pro ...

  9. mysql分表实战

    本文主要讲述如何使用存储过程完成本表.并不讨论其他问题.首先我们得看看手册上关于meger引擎的说明: MERGE存储引擎,也被认识为MRG_MyISAM引擎,是一个相同的可以被当作一个来用的MyIS ...

  10. spring-boot-starter-data-elasticsearch 整合elasticsearch 5.x详解

    1.使用原因 近期公司在开发新的项目用到了elasticsearch ,因为项目框架用的spring Cloud所以依赖全用的是starter,从网上找的信息比较旧,并没有整合elasticsearc ...