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

而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. intellijIDEA Spring配置文件提示: File is included in 4 contexts

    前提: 不影响编码,但是出现淡黄色的背景 解决办法: 打开Project Structure —> 选择Modules -> 选择Spring ->先点减号把之前的都删除掉 -> ...

  2. 虚拟机mac 与主机的网络共享

    1. 主机建立共享文件夹 aaa 2.虚拟机采用桥接 3.mac打开Finder 找到 “前往” 连接服务器”输入“smb://192.168.1.xx”(你电脑的ip地址),点击连接.

  3. Raft 为什么是更易理解的分布式一致性算法(转)

    一致性问题可以算是分布式领域的一个圣殿级问题了,关于它的研究可以回溯到几十年前. 拜占庭将军问题 Leslie Lamport 在三十多年前发表的论文<拜占庭将军问题>(参考[1]). 拜 ...

  4. colgroup中col定义表格单元格宽度

    colgroup中可以使用col来定义表格单元格宽度,可以使用像素(数字),百分比,我们来具体看看有什么不同. 先看一个最基本的:用像素(数字)表示,因为table有个宽度,这里表示占比 <ht ...

  5. 102/107. Binary Tree Level Order Traversal/II

    原文题目: 102. Binary Tree Level Order Traversal 107. Binary Tree Level Order Traversal II 读题: 102. 层序遍历 ...

  6. Hibernate学习笔记1.2(Annotation版本的Helloworld)

    hibernate 3.0之后开始支持Annotation 接着1.1的项目 首先 需要创建model Teacher.java. package com.hw.hibernate.model; pu ...

  7. Oracle Error

    1. TNS:listener does not currently know of service requested in connect descriptor 数据库连接出错

  8. vue 安装sass扩展

    1.创建一个基于 webpack 模板的新项目 $ vue init webpack myvue 1 2.在当前目录下,安装依赖 $ cd myvue $ npm install 1 2 3.安装sa ...

  9. flume kafka 配置指南

    1.官方网站也有配置: https://flume.apache.org/FlumeUserGuide.html#kafka-source 2.clodera 官方配置 https://www.clo ...

  10. SpringJDBC数据库的基本使用

    SpringJDBC的基础使用部分内容 云笔记项目数据库部分采用的是Spring-MyBatis,前面学过了JDBC,SpringJDBC,Mybatis和Spring-MyBatis,有必要重新复习 ...