Indy 10有一个组件叫IdSchedulerOfThreadPool,网上没有其相关使用代码,好在有源代码,于是自己看。其实用起来也还比较简单,主要是实现了维护一个线程池的功能,功能不是很强。不过基于该组件的开发,也可以为我们省了不少代码,增强了些功能。
与该线程池使用相关的类主要有:
TIdSchedulerOfThreadPool 这个不用说
TIdTask(in IdTask.pas) 需要用户继承实现的类,实现参数的传入,及具体的run、BeforeRun、AfterRun功能代码
TIdYarnOfThread(in IdSchedulerOfThread.pas) 需要强制转换的类,只有强制转换后才能访问到线程Thread对象,使用Synchronize来访问VCL控件
------------------------ Unit.pas ----------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, IdSchedulerOfThreadPool, IdYarn,
IdScheduler, IdBaseComponent, IdSchedulerOfThread, Spin;
type
TForm1 = class(TForm)
Memo1: TMemo;
IdSchedulerOfThreadPool1: TIdSchedulerOfThreadPool;
Button4: TButton;
Button2: TButton;
SpinEdit1: TSpinEdit;
Button3: TButton;
procedure Button4Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
aStr: string;
implementation
uses
UnitUploadTask;
{$R *.dfm}
procedure TForm1.Button4Click(Sender: TObject); //线程池添加线程
var
mytask: TUploadTask;
idYarn: TIdYarn;
obj: UploadParamObj;
begin
obj := UploadParamObj.Create;
obj.str := SpinEdit1.Text;
idYarn := IdSchedulerOfThreadPool1.AcquireYarn;
mytask := TUploadTask.Create(idYarn, obj);
IdSchedulerOfThreadPool1.StartYarn(idYarn, mytask);
end;
procedure TForm1.Button3Click(Sender: TObject); //线程池结束线程
begin
IdSchedulerOfThreadPool1.TerminateAllYarns;
end;
procedure TForm1.Button2Click(Sender: TObject); //查看活动线程数
begin
with IdSchedulerOfThreadPool1.ActiveYarns.LockList do try
ShowMessage(IntToStr(count));
finally
IdSchedulerOfThreadPool1.ActiveYarns.UnlockList;
end;
end;
procedure TForm1.FormCreate(Sender: TObject); //初始化线程池
begin
IdSchedulerOfThreadPool1.Init;
end;
end.
------------------------------------- UnitUploadTask.pas ---------------------------------
unit UnitUploadTask;
interface
uses
Classes, SysUtils, IdTask, IdYarn;
type
UploadParamObj = class(TObject)
public
str: string;
end;
TUploadTask = class(TIdTask)
private
thread: TThread;
trytime: Integer;
procedure output;
protected
function Run: Boolean; override;
procedure BeforeRun; override;
procedure AfterRun; override;
public
constructor Create(AYarn: TIdYarn; obj: UploadParamObj);
end;
implementation
uses
Unit1, IdSchedulerOfThread;
constructor TUploadTask.Create(AYarn: TIdYarn; obj: UploadParamObj);
begin
FData := obj;
trytime := 3;
thread := TIdYarnOfThread(AYarn).Thread;
inherited Create(AYarn);
end;
function TUploadTask.Run: Boolean;
begin
thread.Synchronize(thread, output);
Sleep(5000);
if trytime > 0 then
begin
Dec(trytime);
result := True;
end
else
Result := False;
end;
procedure TUploadTask.BeforeRun;
begin
Form1.Memo1.Lines.Add('BeforeRun' + UploadParamObj(FData).str);
end;
procedure TUploadTask.AfterRun;
begin
Form1.Memo1.Lines.Add('AfterRun' + UploadParamObj(FData).str);
end;
procedure TUploadTask.output;
begin
Form1.Memo1.Lines.Add('上传开始,str=' + UploadParamObj(FData).str + ', try=' + IntToStr(trytime) +',id=' + IntToStr(thread.ThreadID));
end;
end.
操作你会发现,线程池是用抛出异常来实现,因此你需要捕获异常来进行线程池满的处理。