第一节:初识多线程
 
1.为什么要学习多线程编程?
 
多线程(多个线程同时运行)编程,亦可称之为异步编程。
有了多线程,主界面才不会因为耗时代码而造成“假死“状态。
有了多线程,才能使多个任务同时执行,最大化利用CPU资源,提高效率。
在安卓编程中,要求必须是多线程,主界面中的代码只要耗时几秒钟,就会触发 ANR 错误。
多线程编程才是工作中的常态。多线程是必须掌握的!越早越好!
 
2.网络上 delphi 多线程 Demo 的误区
 
采用 API 来实现多线程。难度太高,尤其是用指针来传参数,不适合初学者。
用访问界面来举例,出发点就错了。多线程最不擅长的就是操作UI。
网上流行的 demo 就是弄个大循环,再来一个  TextOut 输出。
结果又不得不加上 canvas.Lock, 真是够折腾。
 
3.主线程的定义
 
假设,一个EXE程序,拥有一个 FrmMain (TForm)。
FrmMain 上面有一个 Button1 (TButton) ,一个Edit1 (TEdit)以及一个 Timer1 (TTimer) 。
那么,我们通常把界面(UI)定义为主线程,即 FrmMain 就是主线程。
Button1 的 OnClick 事件中的代码运行于主线程时空。(本教程均统一定义线程时空一词)
使用者在 Edit1 中的输入操作也是主线程时空。
Timer1 的 OnTimer 事件中的代码也运行于主线程时空。
请注意:初学者最容易把 OnTimer 事件误认为是多线程时空。
 
4.普通编程与多线程编程的区别
 
// 普通编程
function Accumulate(num:integer):integer;
var
   i:integer;
begin
   result:=0;
   if num<1 then exit;
   for i:=1 to num do
      result:=result+i;
end;
// 在 Button1 的 OnClick 事件中编写如下代码:
var
   n,Total:integer;
begin
   n:=100;
   Total:=Accumelate(n);
   // 等待计算结果,假设计算需要5分钟,此处就得等待5分钟。
   // 这5分钟内,界面是无法访问的,是假死的。
   // 计算完成,得到结果 Total=5050;
   DoSomeThing; //接着执行此句。
end;
 
// 多线程编程,此为计算线程类
unit uAccumulation;
interface
uses
  Classes;
type
  TAccumulationThread = class;
  TOnAccumulated = procedure(Sender: TAccumulationThread) of object;
  TAccumulationThread = class(TThread)
  protected
    procedure Execute; override;
  public
    Num: integer;
    Total: integer;
    OnAccumulated: TOnAccumulated;
  end;
 
implementation
 
procedure TAccumulationThread.Execute;
var
  i: integer;
begin
  inherited;
  Total := 0;
  if Num > 0 then
  begin
    for i := 1 to Num do
      Total := Total + i
  end;
  // 当计算完成后,就调用  OnAccumulated 通知调用者
  if Assigned(OnAccumulated) then
    OnAccumulated(self);
end;
end.
 
写代码请用英语命名,用正确的单词,时态。切记,非常重要!
 
// 调用多线程
// 在FrmMain 中定义 OnAccumulated 事件函数
Procedure TFrmMain.OnAccumulated(Sender:TAccumulationThread);
var
   sum:integer;
begin
   // 当计算完成时,计算线程就调用本事件函数。
   // 我们在这里就得到了计算结果
   sum:=Sender.Total;
   // 因为这里是线程时空,不能直接把 sum 的值显示到界面上。
   // 如何正确显示,将下一章节中讲解。
end;
 
// 在Button1 的OnClick 事件中编写下面的代码
var
   thd:TAccumulationThread;
begin
   // 此处为主线程时空。
   thd:=TAccumuationThread.Create(true);
   thd.OnAccumulated=Self.OnAccumulated; // Self 指是 FrmMain.
   thd.Num:=100;
   thd.Start; //启动线程,在线程时空中执行 Execute 中的代码。
   //  start 立即返回并执行下一条代码 DoSomeThing;
   //  此时,就有两个线程在同时执行。
   //  1.主线程,也就是此处运行的时代码。
   //  2.计算线程,也就是 Execute 中的代码,这些代码此时运行于多线程时空。
   //  由于是两个线程并行在执行,故此处 DoSomeThing 马上可以执行。
   //  界面也不会假死
   DoSomeThing;
end;
 
通过比较,似乎看出多线程要写更多的代码?要用事件来传递结果来给调用者?
其实都不然,这两点均是面向对象(OO)写法,与线程类无关。
最大的不同是:异步执行,把耗时的计算任务放了入另一个线程时空!
 
多线程带来了效率,同时也带来了更多的麻烦。欲知后事如何,且听下回分解。
 
 
 

delphi 线程教学第一节:初识多线程的更多相关文章

  1. delphi 线程教学第一节:初识多线程(讲的比较浅显),还有三个例子

    http://www.cnblogs.com/lackey/p/6297115.html 几个例子: http://www.cnblogs.com/lackey/p/5371544.html

  2. delphi 线程教学第二节:在线程时空中操作界面(UI)

    第二节:在线程时空中操作界面(UI)   1.为什么要用 TThread ?   TThread 基于操作系统的线程函数封装,隐藏了诸多繁琐的细节. 适合于大部分情况多线程任务的实现.这个理由足够了吧 ...

  3. 第一节 初识RabbitMQ

    原文:第一节 初识RabbitMQ 版权声明:未经本人同意,不得转载该文章,谢谢 https://blog.csdn.net/phocus1/article/details/87280120 1.什么 ...

  4. delphi 线程教学第四节:多线程类的改进

    第四节:多线程类的改进   1.需要改进的地方   a) 让线程类结束时不自动释放,以便符合 delphi 的用法.即 FreeOnTerminate:=false; b) 改造 Create 的参数 ...

  5. delphi 线程教学第六节:TList与泛型

    第六节: TList 与泛型   TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...

  6. 第一节,初识OpenCV3-图像的读、写、显、格式转化等

    之前一直在看深度学习,突然用到了对图像处理的东西,所以过来补充一下OpenCV基础. 就顺便从网上了买了一本OpenCV 3计算机视觉这本书,这本书比较薄,但是目前已经够我用了,在这里就记录一下我的学 ...

  7. delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行

    第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行     以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...

  8. delphi 线程教学第五节:多个线程同时执行相同的任务

    第五节:多个线程同时执行相同的任务   1.锁   设,有一个房间 X ,X为全局变量,它有两个函数  X.Lock 与 X.UnLock; 有如下代码:   X.Lock;      访问资源 P; ...

  9. delphi 线程教学第三节:设计一个有生命力的工作线程

    第三节:设计一个有生命力的工作线程   创建一个线程,用完即扔.相信很多初学者都曾这样使用过. 频繁创建释放线程,会浪费大量资源的,不科学.   1.如何让多线程能多次被复用?   关键是不让代码退出 ...

随机推荐

  1. 保护眼睛,win7家庭版如何修改窗口的背景颜色

    win7的窗口背景色为白色,长时间使用电脑对眼睛的刺激比较大,为了保护眼睛建议改成浅灰色或者淡绿.淡黄色等,可是win7的家庭版里没有[个性化]菜单,那么我们如何修改呢? 首先在[开始]处找到[控制面 ...

  2. Spring之AOP由浅入深(转发:https://www.cnblogs.com/zhaozihan/p/5953063.html)

    1.AOP的作用 在OOP中,正是这种分散在各处且与对象核心功能无关的代码(横切代码)的存在,使得模块复用难度增加.AOP则将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可 ...

  3. 内存写越界导致破环堆结构引起的崩溃问题定位经验[如报错malloc(): memory corruption或free(): invalid next size]

    前段时间开发的一个后端C模块上线后,线上出core,初始时,因为訪问压力不大,所以崩溃是上线3天左右出现的.当时用gdb跟进调用堆栈并检查源代码,发现出core位置的代码沒有啥问题.因为当时开发任务较 ...

  4. 路由helper

    root_url http://192.168.1.110:3000/users/sign_up?inviter=14658733081530 root_path /users/sign_up?inv ...

  5. 【LeetCode】:二叉搜索树

    相关概念: 一棵二叉搜索树(BST)是以一棵二叉树来组织的,可以用链表数据结构来表示,其中,每一个结点就是一个对象,一般地,包含数据内容key和指向孩子(也可能是父母)的指针属性.如果某个孩子结点不存 ...

  6. Example 2 - contour plots

    load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" begin cdf_file = addfile("$N ...

  7. Javascript中闭包的个人理解

       Javascript的一个特殊点就在于它的闭包和回调特性,这两个特性让初学Javascript的我是云里雾里,至今仍在苦苦摸索与理解.在一番苦思之后,整理了一下资料,将自己的理解思路记录下来,以 ...

  8. Python运算和和表达式 学习笔记

    光荣之路Python公开课第二讲 Python运算符和表达式. 一 Python运算符 Python运算符包括 算术运算符,赋值运算符,位运算符,逻辑运算符,身份运算符,成员运算符. 1. 算术运算符 ...

  9. 使用 sqoop 将mysql数据导入到hdfs(import)

    Sqoop 将mysql 数据导入到hdfs(import) 1.创建mysql表 CREATE TABLE `sqoop_test` ( `id` ) DEFAULT NULL, `name` va ...

  10. matlab点云处理函数

    1. pcread: 输入文件名,返回pointCloud类(用于存储点云).eg: pcloud = pcread(“filename.ply”) 2. pcshow: 输入pointCloud类, ...