示例-QWorker基于状态的作业控制演示

为帮助朋友们更好的理解QWorker的使用,今天新增一个示例来演示以下内容:

1、基于信号控制作业的运行状态。主面板上设置了三个按钮:开始、暂停和停止分别控制一个后台作业的状态,而后台作业的实现在另一个窗体单元中实现,是一种松散耦合。

2、基于Delay方法来计划延迟作业,在作业中根据状态重复投寄还是退出执行。

3、窗体释放时清理关联作业。

我们下面说明一下实现的逻辑:

1、主窗体的构造函数中,注册开始、暂停、停止三个状态的信号,并保存其信号编码,以便后面使用。如果不知道相关的编码,可以再次RegisterSignal来获取这个ID。

procedure TfrmMain.FormCreate(Sender: TObject);
begin
FStartSignal := Workers.RegisterSignal('Work.Start');
FPauseSignal := Workers.RegisterSignal('Work.Pause');
FStopSignal := Workers.RegisterSignal('Work.Stop');
frmWork := TfrmWork.Create(Application);
end;

在构造函数的末尾,创建了一个面板窗口,在面板窗口的OnCreate事件中,我们注册了相应信号的处理函数,等待信号的触发。

procedure TfrmWork.FormCreate(Sender: TObject);
begin
Workers.Wait(DoStartWork, frmMain.StartSignal, True);
Workers.Wait(DoPauseWork, frmMain.PauseSignal, True);
Workers.Wait(DoStopWork, frmMain.StopSignal, True);
end;

2、在按下主窗体的开始、暂停和停止按钮时,直接触发相关的信号,而不需要关心有没有代码去实现它。如果有(我们这里当然有),则相应的处理过程会被触发。

procedure TfrmMain.btnPauseClick(Sender: TObject);
begin
Workers.Signal(PauseSignal);
end;

procedure TfrmMain.btnStartClick(Sender: TObject);
begin
Workers.Signal(StartSignal);
end;

procedure TfrmMain.btnStopClick(Sender: TObject);
begin
Workers.Signal(StopSignal);
end;

3、很好,现在TfrmWork的DoStartWork/DoPauseWork/DoStopWork相应的信号处理函数就被触发了。

procedure TfrmWork.DoPauseWork(AJob: PQJob);
begin
Workers.Clear(DoDelayTimer, nil);
frmMain.State := wsPaused;
end;

procedure TfrmWork.DoStartWork(AJob: PQJob);
begin
Workers.Delay(DoDelayTimer, random(1000), nil,True);
if frmMain.State <> wsPaused then
  begin
  SetBounds(Screen.WorkAreaRect.Right - Width, Screen.WorkAreaTop,
    Width, Height);
  Show;
  end;
frmMain.State := wsRunning;
end;

procedure TfrmWork.DoStopWork(AJob: PQJob);
begin
Workers.Clear(DoDelayTimer, nil);
FRuns := 0;
frmMain.State := wsStopped;
Hide;
end;

4、DoDelayTimer执行实际的作业处理过程,在其中,我们在其中显示了一些简单的作业信息,然后再次必要时再次重复延迟触发。

procedure TfrmWork.DoDelayTimer(AJob: PQJob);
var
  ANextDelay: Int64;
begin
ANextDelay := random(1000);
Inc(FRuns);
Label1.Caption := '运行次数:' + IntToStr(FRuns) + '次,末次延迟:' +
  IntToStr((AJob.PopTime - AJob.PushTime) div 10) + 'ms,下一延迟:' +
  IntToStr(ANextDelay) + 'ms';
if (frmMain.State = wsRunning) or (not AJob.IsTerminated) then
  Workers.Delay(DoDelayTimer, ANextDelay * Q1MillSecond, nil,True);
end;

好了,我们现在看看程序的运行结果。

Delaywork

【源码下载】

百度网盘

 

分享到: