如何显示子线程的当前状态
刚刚完成的一个小程序是分析使用竖向排列的24针打印头打印一个数据文件,分析每根针的出针次数等一些参数,给机械开发部门做寿命分析等等。
由于数据文件可能很大,分析时间会比较长,因此要能够显示分析进度,否则让比人以为程序死掉了。
因此,分析工作放在子线程中进行,通过产生“状态改变事件”和“分析结束事件”来通知主线程更新状态。线程定义如下:
//==================================
// MyThread.pas
//===================================//
TStatusChangedEvent = procedure (Percent: Integer) of Object; //状态改变事件
TFinishedEvent = procedure of Object; // 分析结束事件
TMyThread = class(TThread)
Private
FOnStatusChanged: TStatusChangedEvent;
FOnFinished: TFinishedEvent;
protected
procedure Execute; override;
public
property OnStatusChanged: TStatusChangedEvent read FOnStatusChanged write FOnStatusChanged;
property OnFinished: TFinishedEvent read FOnFinished write FOnFinished;
end;
procedure TMyThread.Execute;
var
Percent: Integer;
begin
...
if (Percent 发生了改变) and Assigned(FOnStatusChanged) then
FOnStatusChanged (Percent);
...
// 分析结束
if Assigned (FOnFinished) then
FOnFinished; // 在分析结束时通知主线程
end;
状态显示由一个窗体实现,该窗体有一个进度条,一个状态Label,一个取消按钮,以及一个定时器。定义如下(没有给出进度条、Label、按钮的代码)
//=====================================
// TFrmStatus.pas
//=====================================//
TFrmStatus = class (TForm) // 显示进度的窗体
Timer1: TTimer;
Procedure FormCreate (Sender: TObject);
Private
Procedure SetPercent (Value: Integer);
Procedure SetTerminate (Value: Boolean);
Public
Property Percent: Integer read FPercent write SetPercent;
Property Terminate: Boolean read FTerminate write SetTerminate;
End;
Procedure TFrmStatus. FormCreate (Sender: TObject);
begin
FTerminate := false;
Timer1.enable := false;
end;
procedure TFrmStatus. SetPercent(Value: Integer); // 设置百分比进度
begin
// 设置控件状态以表示当前的百分比进度
end;
procedure TFrmStatus.SetTerminate(Value: boolean;) // 设置结束状态
begin
if FTerminate <> Value then
begin
FTerminate := Value;
Timer1.Interval := 2;
Timer1.Enable := true;
end;
end;
procedure TFrmStatus.Timer1Timer(Sender: TObject); // 响应定时器,关闭窗口,返回mrOk
begin
Close;
ModalResult := mrOk;
end;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
主窗体负责创建分析线程和状态显示窗体,并响应分析线程产生的“状态改变事件”和“分析结束事件”。
// 主窗体
TFrmMain := class(TForm)
private
FFrmStatus: TFrmStatus;
procedure DoStatusChange(Percent: Integer); // 响应分析进度改变事件
procedure DoFinished; // 响应分析结束事件
public
procedure Do;
end;
// 运行分析
procedure TFrmMain.Do;
var
MyThread: TMyThread;
FrmStatus: TFrmStatus;
begin
try
MyThread := TMyThread.Create(true);
MyThread.OnStatusChange := DoStatusChange;
MyThread.OnFinished := DoFinished;
try
FrmStatus := TFrmStatus.Create(nil);
FFrmStatus := FrmStatus;
MyThread.Resume; // 启动线程
if FrmStatus.ShowModal = mrOk then
ShowAnalyseResult; // 显示分析结果
finally
FFrmStatus := nil;
FrmStatus.Free;
end;
finally
MyThread.FreeOnTerminate := true;
MyThread.Terminate;
end;
end;
// 响应状态改变事件,显示进度
procedure TFrmMain.DoStatusChange(Percent: Integer)
begin
if FFrmStatus <> nil then
FFrmStatus.Percent := Percent;
end;