⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uthreadmanager.~pas

📁 本模型是在内存中创建 n 个工人线程, 1. 在无任务时处于休眠状态,不占用CPU时间, 2. 在有任务时,被唤醒,取得任务,完成任务后,又自动休眼.
💻 ~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 + -