📄 uthreadmanager.~pas
字号:
{*******************************************************}
{ }
{ 简单的线程池模型 }
{ }
{ 单元名: uThreadManager.pas }
{ }
{ 作 者: 隐神 }
{ }
{ 版权所有 (C) 2006 独家村一号 }
{ }
{*******************************************************}
{*******************************************************
版本 :
主要功能 : 主要功能
创建日期 : 十月
版本 :
修改日期 :
修改者 :
修改内容 :
*******************************************************}
unit uThreadManager;
interface
uses
Windows, SysUtils, Classes, uPubStructs;
type
TTaskOption = (eoRead, eoWrite);
//线程池管理者
TThreadManager = class(TObject)
private
FDebugCount: Integer;
//记录工人线程的处理结果
FAnswer: TMemoryStream;
//红绿灯
FEvent: THandle;
//线程池
FPool: TList;
//任务池 用 TThreadList 会更安全, 这里故意用 List 做实验
FTaskPool: TList;
//工人数
FWorkerCount: Integer;
//创建工人
procedure CreateWorkerThread(AWorkerCount: integer);
//添加/取得任务
procedure ManageTask(const AOption: TTaskOption; var VTask: PTask);
//供工人回写出处理结果的事件过程。
procedure OnAnswerEvent(var VTask: PTask);
//供工人取得任务的事件过程。
procedure OnGetTaskEvent(var VTask: PTask);
public
FCloseEvent: THandle;
constructor Create(AWorkerCount: integer);
destructor Destroy; override;
//供主进程写入任务的函数
procedure SetTask(var ATask: PTask);
end;
implementation
uses uThreadWorker;
{ TThreadManager }
var
//临界区同步变量
MANAGE_TASK_CS, SAVE_ANSWER_CS: TRTLCriticalSection;
{
******************************** TThreadManager ********************************
}
constructor TThreadManager.Create(AWorkerCount: integer);
begin
inherited Create;
FDebugCount := 0;
FAnswer := TMemoryStream.Create;
FPool := TList.Create;
FEvent := Windows.CreateEvent(nil, True, false, nil);
FCloseEvent := Windows.CreateEvent(nil, True, False, nil);
FWorkerCount := AWorkerCount;
FTaskPool := TList.Create;
//初始化临界区
InitializeCriticalSection(MANAGE_TASK_CS);
InitializeCriticalSection(SAVE_ANSWER_CS);
CreateWorkerThread(FWorkerCount);
end;
destructor TThreadManager.Destroy;
var
i: Integer;
begin
//释放工人线程
for i := FWorkerCount - 1 downto 0 do
begin
{1 如果线程中有 FreeOnTerminate := True; 用
ThreadWorker.Terminate;
Terminate 并不直接终止线程, 只是将线程的 Terminated 置为 TRUE
}
{2. 如果线程中无 FreeOnTerminate := True;
且
destructor TThreadWorker.Destroy;
begin
Self.Terminate;
inherited;
end;
用
FreeAndNil(ThreadWorker);
}
TThreadWorker(FPool[i]).Terminate;
//todo: 如果线程正在休眠呢?
//暂时用不断地开绿灯唤醒休眠的工人线程的方法试试
SetEvent(FEvent);
FPool.Delete(i);
Sleep(100);
end;
FreeAndNil(FPool);
//释放未完成的任务
for i := FTaskPool.Count - 1 downto 0 do
begin
Dispose(FTaskPool[i]);
FTaskPool.Delete(i);
end;
FreeAndNil(FTaskPool);
FreeAndNil(FAnswer);
//删除临界区同步变量
DeleteCriticalSection(MANAGE_TASK_CS);
//删除临界区同步变量
DeleteCriticalSection(SAVE_ANSWER_CS);
//删除同步事件
CloseHandle(FEvent);
inherited;
end;
procedure TThreadManager.CreateWorkerThread(AWorkerCount: integer);
var
i: Integer;
Worker: TThreadWorker;
begin
for i := 1 to AWorkerCount do
begin
Worker := TThreadWorker.Create(False, FEvent, OnGetTaskEvent,
OnAnswerEvent, i);
FPool.Add(Worker);
Sleep(50);
end;
end;
procedure TThreadManager.ManageTask(const AOption: TTaskOption;
var VTask: PTask);
begin
//todo: 测试时发现并没有同步
//进入临界区同步
EnterCriticalSection(MANAGE_TASK_CS);
try
case AOption of
eoRead: //取任务
begin
//如有任务, 取任务
if FTaskPool.Count > 0 then
begin
VTask := PTask(FTaskPool[0]);
FTaskPool.Delete(0);
end
else
VTask := nil;
//如没任务, 转红灯, 让工人们休息一会.
if FTaskPool.Count = 0 then
ResetEvent(FEvent);
end;
eoWrite: //添加任务
begin
FTaskPool.Add(VTask);
VTask := nil;
//亮绿灯, 唤醒工人, 周扒皮一下.
SetEvent(FEvent);
end;
end; {case}
finally
{ [修改者:谁变]try..finally保护,防卡线程进入监界面出现异常,
无法执行离开监界区命令 }
LeaveCriticalSection(MANAGE_TASK_CS);
end;
end;
procedure TThreadManager.OnAnswerEvent(var VTask: PTask);
begin
//todo: 测试时发现并没有同步
//进入临界区同步
EnterCriticalSection(SAVE_ANSWER_CS);
try
FAnswer.Write(VTASK^.FCMD[1], Length(VTask^.FCMD));
Dispose(VTask);
Inc(FDebugCount);
//todo: 输结果看看。
if FDebugCount >= 80000 then
begin
FAnswer.SaveToFile('.\Answer.txt');
end;
finally
//离开临界区同步
LeaveCriticalSection(SAVE_ANSWER_CS);
end;
end;
procedure TThreadManager.OnGetTaskEvent(var VTask: PTask);
begin
ManageTask(eoRead, VTask);
end;
procedure TThreadManager.SetTask(var ATask: PTask);
begin
ManageTask(eoWrite, ATask);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -