DELPHI线程池代码【uThreadPool.PAS】

ajmxj 2011-09-23 10:52:58
有没有人用过这个线程池,不知道怎么调用啊,哪个高人写个简单的DEMO,非常感谢,解决了再加100分!!

部分代码,全部代码地址:http://blog.csdn.net/babyvspp/article/details/2008234

unit uThreadPool;

{ aPool.AddRequest(TMyRequest.Create(RequestParam1, RequestParam2, ...)); }

interface
uses
Windows,
Classes;

// 是否记录日志
// {$DEFINE NOLOGS}

type
TCriticalSection = class(TObject)
protected
FSection: TRTLCriticalSection;
public
constructor Create;
destructor Destroy; override;
// 进入临界区
procedure Enter;
// 离开临界区
procedure Leave;
// 尝试进入
function TryEnter: Boolean;
end;

type
// 储存请求数据的基本类
TWorkItem = class(TObject)
public
// 是否有重复任务
function IsTheSame(DataObj: TWorkItem): Boolean; virtual;
// 如果 NOLOGS 被定义,则禁用。
function TextForLog: string; virtual;
end;

type
TThreadsPool = class;

//线程状态
TThreadState = (tcsInitializing, tcsWaiting, tcsGetting, tcsProcessing,
tcsProcessed, tcsTerminating, tcsCheckingDown);
// 工作线程仅用于线程池内, 不要直接创建并调用它。
TProcessorThread = class(TThread)
private
// 创建线程时临时的Event对象, 阻塞线程直到初始化完成
hInitFinished: THandle;
// 初始化出错信息
sInitError: string;
// 记录日志
procedure WriteLog(const Str: string; Level: Integer = 0);
protected
// 线程临界区同步对像
csProcessingDataObject: TCriticalSection;
// 平均处理时间
FAverageProcessing: Integer;
// 等待请求的平均时间
FAverageWaitingTime: Integer;
// 本线程实例的运行状态
FCurState: TThreadState;
// 本线程实例所附属的线程池
FPool: TThreadsPool;
// 当前处理的数据对像。
FProcessingDataObject: TWorkItem;
// 线程停止 Event, TProcessorThread.Terminate 中开绿灯
hThreadTerminated: THandle;
uProcessingStart: DWORD;
// 开始等待的时间, 通过 GetTickCount 取得。
uWaitingStart: DWORD;
// 计算平均工作时间
function AverageProcessingTime: DWORD;
// 计算平均等待时间
function AverageWaitingTime: DWORD;
procedure Execute; override;
function IamCurrentlyProcess(DataObj: TWorkItem): Boolean;
// 转换枚举类型的线程状态为字串类型
function InfoText: string;
// 线程是否长时间处理同一个请求?(已死掉?)
function IsDead: Boolean;
// 线程是否已完成当成任务
function isFinished: Boolean;
// 线程是否处于空闲状态
function isIdle: Boolean;
// 平均值校正计算。
function NewAverage(OldAvg, NewVal: Integer): Integer;
public
Tag: Integer;
constructor Create(APool: TThreadsPool);
destructor Destroy; override;
procedure Terminate;
end;

// 线程初始化时触发的事件
TProcessorThreadInitializing = procedure(Sender: TThreadsPool; aThread:
TProcessorThread) of object;
// 线程结束时触发的事件
TProcessorThreadFinalizing = procedure(Sender: TThreadsPool; aThread:
TProcessorThread) of object;
// 线程处理请求时触发的事件
TProcessRequest = procedure(Sender: TThreadsPool; WorkItem: TWorkItem;
aThread: TProcessorThread) of object;
TEmptyKind = (
ekQueueEmpty, //任务被取空后
ekProcessingFinished // 最后一个任务处理完毕后
);
// 任务队列空时触发的事件
TQueueEmpty = procedure(Sender: TThreadsPool; EmptyKind: TEmptyKind) of
object;


TThreadsPool = class(TComponent)
private
csQueueManagment: TCriticalSection;
csThreadManagment: TCriticalSection;
FProcessRequest: TProcessRequest;
FQueue: TList;
FQueueEmpty: TQueueEmpty;
// 线程超时阀值
FThreadDeadTimeout: DWORD;
FThreadFinalizing: TProcessorThreadFinalizing;
FThreadInitializing: TProcessorThreadInitializing;
// 工作中的线程
FThreads: TList;
// 执行了 terminat 发送退出指令, 正在结束的线程.
FThreadsKilling: TList;
// 最少, 最大线程数
FThreadsMax: Integer;
// 最少, 最大线程数
FThreadsMin: Integer;
// 池平均等待时间
function PoolAverageWaitingTime: Integer;
procedure WriteLog(const Str: string; Level: Integer = 0);
protected
FLastGetPoint: Integer;
// Semaphore, 统计任务队列
hSemRequestCount: THandle;
// Waitable timer. 每30触发一次的时间量同步
hTimCheckPoolDown: THandle;
// 线程池停机(检查并清除空闲线程和死线程)
procedure CheckPoolDown;
// 清除死线程,并补充不足的工作线程
procedure CheckThreadsForGrow;
procedure DoProcessed;
procedure DoProcessRequest(aDataObj: TWorkItem; aThread: TProcessorThread);
virtual;
procedure DoQueueEmpty(EmptyKind: TEmptyKind); virtual;
procedure DoThreadFinalizing(aThread: TProcessorThread); virtual;
// 执行事件
procedure DoThreadInitializing(aThread: TProcessorThread); virtual;
// 释放 FThreadsKilling 列表中的线程
procedure FreeFinishedThreads;
// 申请任务
procedure GetRequest(out Request: TWorkItem);
// 清除死线程
procedure KillDeadThreads;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
// 就进行任务是否重复的检查, 检查发现重复就返回 False
function AddRequest(aDataObject: TWorkItem; CheckForDoubles: Boolean =
False): Boolean; overload;
// 转换枚举类型的线程状态为字串类型
function InfoText: string;
published
// 线程处理任务时触发的事件
property OnProcessRequest: TProcessRequest read FProcessRequest write
FProcessRequest;
// 任务列表为空时解发的事件
property OnQueueEmpty: TQueueEmpty read FQueueEmpty write FQueueEmpty;
// 线程结束时触发的事件
property OnThreadFinalizing: TProcessorThreadFinalizing read
FThreadFinalizing write FThreadFinalizing;
// 线程初始化时触发的事件
property OnThreadInitializing: TProcessorThreadInitializing read
FThreadInitializing write FThreadInitializing;
// 线程超时值(毫秒), 如果处理超时,将视为死线程
property ThreadDeadTimeout: DWORD read FThreadDeadTimeout write
FThreadDeadTimeout default 0;
// 最大线程数
property ThreadsMax: Integer read FThreadsMax write FThreadsMax default 1;
// 最小线程数
property ThreadsMin: Integer read FThreadsMin write FThreadsMin default 0;
end;

type
//日志记志函数
TLogWriteProc = procedure(
const Str: string; //日志
LogID: Integer = 0;
Level: Integer = 0 //Level = 0 - 跟踪信息, 10 - 致命错误
);

var
WriteLog: TLogWriteProc; // 如果存在实例就写日志

implementation
uses
SysUtils;



调用方法:

// 创建线程池
FThreadPool := TThreadsPool.Create(Self); // 创建线程池
FThreadPool.ThreadsMin := 5; // 初始工作线程数
FThreadPool.ThreadsMax := 50; // 最大允许工作线程数
FThreadPool.OnProcessRequest := DealwithCommRecvData; // 线程工作函数(DealwithCommRecvData在工作者线程的Execute方法中被调用)


// 使用线程池
var
 AWorkItem: TRecvCommDataWorkItem; // 继承自TWorkItem
begin
 AWorkItem := TRecvCommDataWorkItem.Create;
 Move(PData[0], AWorkItem.FRecvData[0], PDataLen);
 AWorkItem.FRecvDataLen := PDataLen;
 FThreadPool.AddRequest(AWorkItem); // 向线程池分配一个任务
end;
...全文
654 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyhoo163 2011-09-25
  • 打赏
  • 举报
回复
关注。
ajmxj 2011-09-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jiang188136923 的回复:]
去我的资源下载,已写好DEMO.
[/Quote]
初始化参数,然后点开始任务就没反应了,请问是什么情况?
rainychan2009 2011-09-23
  • 打赏
  • 举报
回复
var
 AWorkItem: TRecvCommDataWorkItem; // 继承自TWorkItem
begin
 AWorkItem := TRecvCommDataWorkItem.Create;
 Move(PData[0], AWorkItem.FRecvData[0], PDataLen);
 AWorkItem.FRecvDataLen := PDataLen;
 FThreadPool.AddRequest(AWorkItem); // 向线程池分配一个任务
end;
aaron6966 2011-09-23
  • 打赏
  • 举报
回复
标记一下,以后看
bdmh 2011-09-23
  • 打赏
  • 举报
回复
你不是都已经贴出调用方法了
cntigercat 2011-09-23
  • 打赏
  • 举报
回复
留个标记,学习
jiangzs188136923 2011-09-23
  • 打赏
  • 举报
回复
去我的资源下载,已写好DEMO.
delphi线程池单元文件uThreadPool.pas,用法如下 type TRecvCommDataWorkItem=class(TWorkItem) public // updatetime,addtime:TDateTime; // orderid,ordertype,urljson,loadcount,savepath:string; url,Filename:string; total,order:Integer; _orderid:string; failedcount:Integer; IFCoverFile:Boolean; // 线程处理请求时触发的事件 procedure DealwithCommRecvData(Sender: TThreadsPool; WorkItem: TWorkItem; aThread: TProcessorThread); // 线程初始化时触发的事件 procedure TProcessorThreadInitializing(Sender: TThreadsPool; aThread:TProcessorThread); // 线程结束时触发的事件 procedure TProcessorThreadFinalizing(Sender: TThreadsPool; aThread:TProcessorThread); //任务队列空时触发的事件 procedure TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); end; 先声明一个类 然后用法 FThreadPool := TThreadsPool.Create(nil); // 创建线程池 FThreadPool.ThreadsMin := 10; // 初始工作线程数 FThreadPool.ThreadsMax := 100; // 最大允许工作线程数 AWorkItem := TRecvCommDataWorkItem.Create; ISAllOverLoad:=False; AWorkItem.url:=urljson; AWorkItem.order:=i; AWorkItem.total:=JA.Count; AWorkItem.Filename:=savefilepath; AWorkItem._orderid:=orderid; AWorkItem.IFCoverFile:=IFCoverFile; FThreadPool.AddRequest(AWorkItem,True); // 向线程池分配一个任务 FThreadPool.OnProcessRequest := AWorkItem.DealwithCommRecvData; FThreadPool.OnThreadInitializing := AWorkItem.TProcessorThreadInitializing; FThreadPool.OnThreadFinalizing := AWorkItem.TProcessorThreadFinalizing; FThreadPool.OnQueueEmpty := AWorkItem.TQueueEmpty; 仔细看下线程池单元的函数说明轻松搞定。 procedure TRecvCommDataWorkItem.TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); begin if EmptyKind=ekProcessingFinished then begin try if Assigned(geturl) then //存在的bug 如果下载文件存在的不行 begin //Sleep(200); //激活线程可能会发生在 休眠之前!! ISAl
Delphi线程池实现多线程FTP分段下载组件 by :renshouren mail:114032666@qq.com QQ:114032666 2019.10.05 使用的组件 1、TIdFTP Indy FTP客户端 2、TThreadsPool 线程池 工作原理及流程 调用本单元,将自动在程序初始化时生成线程池TThreadPoolDown实例 Share_ThreadPool_FTPDown 一、外部调用方法 外部只需要一次性调用 FtpDown() 函数向线程池加入下载任务,下载任务执行中的事件会通过调用时注册的 回调函数 AFtpDownEvent 进行通知。 二、内部工作流程 1、FtpDown()函数将调用TThreadPoolDown.AddFtpDown() ,然后调用TADownFileObj.MakeGetFileSizeObj()分配线程任务 本过程中,将向回调函数 AFtpDownEvent 触发 HEM_ADDURL 事件通知 2、工作线程调用任务对象TFTPHeadObj.DoThreadExecute 过程获取远程文件大小 备注:该功能实际使用到FTP命令SIZE,该命令一些老版本FTP服务器有可能不支持 本过程中,若获取文件大小成功,将向回调函数 AFtpDownEvent 触发 HEM_GETSIZE 事件通知, 若失败,则触发 HEM_ERROR 事件通知 3、得到远程文件大小后,调用TADownFileObj.MakeGetObjs(),分配获取远程文件线程任务 本过程中,开始时,将向回调函数 AFtpDownEvent 触发 HEM_WORKBEGIN 事件通知 在接收数据时,向回调函数 AFtpDownEvent 触发 HEM_WORK 事件通知 4、工作线程调用任务对象 TFTPGetObj.DoThreadExecute 实际下载远程文件数据块 每一个数据块下载任务完成后,触发 HEM_BLOCKOK 事件通知 5、所有数据块完成后,将调用 DoDownloadOK 函数,触发 HEM_DOWNOK 事件通知

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧