delphi 线程教学第六节:TList与泛型
unit uFooList;interfaceuses Generics.Collections;type TFooList <T>= class(TList<T>) private procedure FreeAllItems; protected procedure FreeItem(Item: T);virtual; // 子类中需要重载此过程。以确定到底如何释放 Item // 如果是 Item 是指针,就用 Dispose(Item); // 如果是 Item 是TObject ,就用 Item.free; public destructor Destroy;override; procedure ClearAllItems; procedure Lock; // 给本类设计一把锁。 procedure Unlock; end; // 定义加入到 List 的 Item 都由 List 来释放。 // 定义释放规则很重要!只有规则清楚了,才不会乱套。 // 通过这样简单的改造, TList 立马好用 N 倍。implementation{ TFooList<T> }procedure TFooList<T>.ClearAllItems;begin FreeAllItems; Clear;end;destructor TFooList<T>.Destroy;begin FreeAllItems; inherited;end;procedure TFooList<T>.FreeAllItems;var Item: T;begin for Item in self do FreeItem(Item);end;procedure TFooList<T>.FreeItem(Item: T);beginend;procedure TFooList<T>.Lock;begin System.TMonitor.Enter(self);end;procedure TFooList<T>.Unlock;begin System.TMonitor.Exit(self);end;end.unit uFrmMain; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, uCountThread, uFooList;type TCountThreadList = Class(TFooList<TCountThread>) // 定义一个线程 List protected procedure FreeItem(Item: TCountThread); override; // 指定 Item 的释放方式。 end; TNumList = Class(TFooList<Integer>); // 定义一个 Integer List TFrmMain = class(TForm) memMsg: TMemo; edtNum: TEdit; btnWork: TButton; lblInfo: TLabel; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure btnWorkClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); private { Private declarations } FNumList: TNumList; FCountThreadList: TCountThreadList; FBuff: TStringList; FBuffIndex: Integer; FBuffMaxIndex: Integer; FWorkedCount: Integer; procedure DispMsg(AMsg: string); procedure OnThreadMsg(AMsg: string); function OnGetNum(Sender: TCountThread): Boolean; procedure OnCounted(Sender: TCountThread); procedure LockCount; procedure UnlockCount; public { Public declarations } end;var FrmMain: TFrmMain;implementation{$R *.dfm}{ TFrmMain }{ TCountThreadList }procedure TCountThreadList.FreeItem(Item: TCountThread);begin inherited; Item.Free;end;procedure TFrmMain.btnWorkClick(Sender: TObject);var s: string; thd: TCountThread;begin btnWork.Enabled := false; FWorkedCount := 0; FBuffIndex := 0; FBuffMaxIndex := FNumList.Count - 1; s := '共' + IntToStr(FBuffMaxIndex + 1) + '个任务,已完成:' + IntToStr(FWorkedCount); lblInfo.Caption := s; for thd in FCountThreadList do begin thd.StartThread; end;end;procedure TFrmMain.DispMsg(AMsg: string);begin memMsg.Lines.Add(AMsg);end;procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);begin // 防止计算期间退出 LockCount; // 请思考,这里为什么要用 LockCount; CanClose := btnWork.Enabled; if not btnWork.Enabled then DispMsg('正在计算,不准退出!'); UnlockCount;end;procedure TFrmMain.FormCreate(Sender: TObject);var thd: TCountThread; i: Integer;begin FCountThreadList := TCountThreadList.Create; // 可以看出用了 List 之后,线程数量指定更加灵活。 // 多个线程在一个 List 中,这个 List 可以理解为线程池。 for i := 1 to 3 do begin thd := TCountThread.Create(false); FCountThreadList.Add(thd); thd.OnStatusMsg := self.OnThreadMsg; thd.OnGetNum := self.OnGetNum; thd.OnCounted := self.OnCounted; thd.ThreadName := '线程' + IntToStr(i); end; FNumList := TNumList.Create; // 构造一组数据用来测试 FNumList.Add(100); FNumList.Add(136); FNumList.Add(306); FNumList.Add(156); FNumList.Add(152); FNumList.Add(106); FNumList.Add(306); FNumList.Add(156); FNumList.Add(655); FNumList.Add(53); FNumList.Add(99); FNumList.Add(157);end;procedure TFrmMain.FormDestroy(Sender: TObject);begin FNumList.Free; FCountThreadList.Free;end;procedure TFrmMain.LockCount;begin System.TMonitor.Enter(btnWork);end;procedure TFrmMain.UnlockCount;begin System.TMonitor.Exit(btnWork);end;procedure TFrmMain.OnCounted(Sender: TCountThread);var s: string;begin LockCount; // 锁不同的对象,宜用不同的锁。 // 每把锁的功能要单一,锁的粒度要最小化。才能提高效率。 s := Sender.ThreadName + ':' + IntToStr(Sender.Num) + '累加和为:'; s := s + IntToStr(Sender.Total); OnThreadMsg(s); inc(FWorkedCount); s := '共' + IntToStr(FBuffMaxIndex + 1) + '个任务,已完成:' + IntToStr(FWorkedCount); TThread.Synchronize(nil, procedure begin lblInfo.Caption := s; end); if FWorkedCount >= FBuffMaxIndex + 1 then begin TThread.Synchronize(nil, procedure begin DispMsg('已计算完成'); btnWork.Enabled := true; // 恢复按钮状态。 end); end; UnlockCount;end;function TFrmMain.OnGetNum(Sender: TCountThread): Boolean;begin // 将多个线程访问 FNumList 排队。 FNumList.Lock; try if FBuffIndex > FBuffMaxIndex then begin result := false; end else begin Sender.Num := FNumList[FBuffIndex]; result := true; inc(FBuffIndex); end; finally FNumList.Unlock; end;end;procedure TFrmMain.OnThreadMsg(AMsg: string);begin TThread.Synchronize(nil, procedure begin DispMsg(AMsg); end);end;end.delphi 线程教学第六节:TList与泛型的更多相关文章
- delphi 线程教学第五节:多个线程同时执行相同的任务
第五节:多个线程同时执行相同的任务 1.锁 设,有一个房间 X ,X为全局变量,它有两个函数 X.Lock 与 X.UnLock; 有如下代码: X.Lock; 访问资源 P; ...
- delphi 线程教学第四节:多线程类的改进
第四节:多线程类的改进 1.需要改进的地方 a) 让线程类结束时不自动释放,以便符合 delphi 的用法.即 FreeOnTerminate:=false; b) 改造 Create 的参数 ...
- delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行
第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行 以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...
- delphi 线程教学第二节:在线程时空中操作界面(UI)
第二节:在线程时空中操作界面(UI) 1.为什么要用 TThread ? TThread 基于操作系统的线程函数封装,隐藏了诸多繁琐的细节. 适合于大部分情况多线程任务的实现.这个理由足够了吧 ...
- delphi 线程教学第一节:初识多线程
第一节:初识多线程 1.为什么要学习多线程编程? 多线程(多个线程同时运行)编程,亦可称之为异步编程. 有了多线程,主界面才不会因为耗时代码而造成“假死“状态. 有了多线程,才能使多个任务同时 ...
- delphi 线程教学第一节:初识多线程(讲的比较浅显),还有三个例子
http://www.cnblogs.com/lackey/p/6297115.html 几个例子: http://www.cnblogs.com/lackey/p/5371544.html
- delphi 线程教学第三节:设计一个有生命力的工作线程
第三节:设计一个有生命力的工作线程 创建一个线程,用完即扔.相信很多初学者都曾这样使用过. 频繁创建释放线程,会浪费大量资源的,不科学. 1.如何让多线程能多次被复用? 关键是不让代码退出 ...
- ASP.NET MVC深入浅出系列(持续更新) ORM系列之Entity FrameWork详解(持续更新) 第十六节:语法总结(3)(C#6.0和C#7.0新语法) 第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字 各种通讯连接方式 设计模式篇 第十二节: 总结Quartz.Net几种部署模式(IIS、Exe、服务部署【借
ASP.NET MVC深入浅出系列(持续更新) 一. ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态模 ...
- TMsgThread, TCommThread -- 在delphi线程中实现消息循环
http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使 ...
随机推荐
- 前端之CSS内容
一.CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). 二.CSS语法 1 ...
- 福利:100G Java全套学习视频免费送了
嗯 是的 众所周知 java工会自开办以来 一直致力于分享一些 java技术总结 学习方法..等等等 所以 从我做这个公众号以来 我的手机就没有消停过一天 因为 每天都有很多粉丝问我 "您好 ...
- kafka知识体系
最近一直在整理kafka相关资料,以构建自己的知识体系. 主要分为五大方面: Kafka设计与原理分析 Kafka配置分析 Kafka运维手册 Kafka编程开发 kafka源码分析
- [Ahoi2005]LANE 航线规划
题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...
- [BZOJ]1177: [Apio2009]Oil
题目大意:给出一个n*m的矩阵,选出3个不相交的k*k子矩阵,使得子矩阵中元素和最大.(k<=n,m<=1500) 思路:选出的子矩阵有3种情况:横着排三个.竖着排三个.三角状分布(其中有 ...
- ●CodeForces 280D k-Maximum Subsequence Sum
题链: http://codeforces.com/problemset/problem/280/D 题解: 神题,巨恶心.(把原来的那个dp题升级为:序列带修 + 多次询问区间[l,r]内取不超过k ...
- [bzoj4824][Cqoi2017]老C的键盘
来自FallDream的博客,未经允许,请勿转载,谢谢. 老 C 是个程序员. 作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序在某种 ...
- 【NOIP2013货车运输】
描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...
- codeblocks设置背景主题
一. 首先进入codeblocks官网找到colour theme代码. codeblocks官网代码地址:http://wiki.codeblocks.org/index.php?title=Syn ...
- C++ 中私有继承、保护继承与公有继承
区别 下面通过一个示例来介绍三种继承的区别. 定义一个基类(假设为一个快退休的富豪): class RichMan { public: RichMan(); ~RichMan(); int m_com ...