qworker 实例

unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, qrbtree, qworker, SyncObjs, ExtCtrls, dateutils;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button4: TButton;
    Label1: TLabel;
    Timer1: TTimer;
    Label2: TLabel;
    Button3: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    Button9: TButton;
    Button10: TButton;
    Button11: TButton;
    Button12: TButton;
    Button13: TButton;
    Button14: TButton;
    Button15: TButton;
    Label3: TLabel;
    Button16: TButton;
    Button17: TButton;
    Label4: TLabel;
    Button18: TButton;
    Button19: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure Button9Click(Sender: TObject);
    procedure Button10Click(Sender: TObject);
    procedure Button11Click(Sender: TObject);
    procedure Button12Click(Sender: TObject);
    procedure Button13Click(Sender: TObject);
    procedure Button14Click(Sender: TObject);
    procedure Button15Click(Sender: TObject);
    procedure Button16Click(Sender: TObject);
    procedure Button17Click(Sender: TObject);
    procedure Button18Click(Sender: TObject);
    procedure Button19Click(Sender: TObject);
  private
    { Private declarations }
    FSignalId: Integer;
    procedure DoJobProc(AJob: PQJob);
    procedure DoPostJobDone(AJob: PQJob);
    procedure DoMainThreadWork(AJob: PQJob);
    procedure DoPostJobMsg(var AMsg: TMessage); message WM_APP;
    procedure SignalWaitProc(AJob: PQJob);
    procedure DoSignalJobMsg(var AMsg: TMessage); message WM_APP + 1;
    procedure DoTimerProc(AJob: PQJob);
    procedure DoTimerJobMsg(var AMsg: TMessage); message WM_APP + 2;
    procedure DoLongtimeWork(AJob: PQJob);
    procedure DoLongworkDone(AJob: PQJob);
    procedure DoAtTimeJob1(AJob: PQJob);
    procedure DoAtTimeJob2(AJob: PQJob);
    procedure DoDelayJob(AJob: PQJob);
    procedure DoCancelJob(AJob: PQJob);
    procedure DoNullJob(AJob: PQJob);
    procedure DoCOMJob(AJob: PQJob);
    procedure DoRandDelay(AJob: PQJob);
    procedure SelfTerminateJob(AJob: PQJob);
  public
    { Public declarations }
  end;

  TAutoFreeTestObject = class
  public
    constructor Create; overload;
    destructor Destroy; override;
  end;

  PAutoFreeRecord = ^TAutoFreeRecord;

  TAutoFreeRecord = record
    Id: Integer;
  end;

var
  Form1: TForm1;

implementation

uses
  qstring, comobj;
{$R *.dfm}

procedure TForm1.SelfTerminateJob(AJob: PQJob);
begin
  Label4.Caption := '自结束作业已运行 ' + IntToStr(AJob.Runs) + '次';
  if AJob.Runs = 3 then
  begin
    AJob.IsTerminated := True;
    Label4.Caption := '自结束作业已结束.';
  end;
end;

procedure TForm1.SignalWaitProc(AJob: PQJob);
begin
  PostMessage(Handle, WM_APP + 1, AJob.Runs, 0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Workers.Signal(FSignalId);
end;

procedure TForm1.Button10Click(Sender: TObject);
var
  ATime: TDateTime;
begin
  ATime := Now;
  ATime := IncSecond(ATime, 10);
  Workers.at(DoAtTimeJob2, ATime, QWorker.Q1Hour, nil, True);
  ShowMessage('这个任务将在' + FormatDateTime('hh:nn:ss.zzz', ATime) + '时第一次启动,以后每隔1小时定时启动一次。');
end;

procedure TForm1.Button11Click(Sender: TObject);
begin
  Workers.Post(DoCancelJob, Pointer(1));
//直接取消简单作业队列中的作业,正常情况下是没来的及执行
  Workers.Clear(DoCancelJob, Pointer(1));
  Workers.Post(DoCancelJob, Pointer(2));
//作业已经进行了,取消操作会等待作业完成
  Sleep(100);
  Workers.Clear(DoCancelJob, Pointer(2));
//重复作业
  Workers.Post(DoCancelJob, 1000, Pointer(3));
//直接取消重复作业队列中的作业
  Workers.Clear(DoCancelJob, Pointer(3));
//重复作业
  Workers.Post(DoCancelJob, 1000, Pointer(4));
  Sleep(200);
//直接取消重复作业队列中的作业
  Workers.Clear(DoCancelJob, Pointer(4));
//信号作业队列
  Workers.Wait(DoCancelJob, FSignalId, Pointer(5));
  Workers.Clear(DoCancelJob, Pointer(5));
end;

procedure TForm1.Button12Click(Sender: TObject);
var
  AData: PAutoFreeRecord;
begin
  Workers.Post(DoNullJob, TAutoFreeTestObject.Create, false, jdfFreeAsObject);
  New(AData);
  Workers.Delay(DoNullJob, 1000, AData, false, jdfFreeAsRecord);
end;

procedure TForm1.Button13Click(Sender: TObject);
begin
  Workers.Post(DoCOMJob, nil);
end;

procedure TForm1.Button14Click(Sender: TObject);
begin
  Workers.Signal('MySignal.Start');
  Workers.Signal('MySignal.Start');
  Workers.Post(DoNullJob, nil);
  Workers.Clear('MySignal.Start');
end;

procedure TForm1.Button15Click(Sender: TObject);
begin
  Workers.Delay(DoRandDelay, Q1Second, nil);
end;

procedure DoGlobalJob(AJob: PQJob);
begin
  ShowMessage('全局函数作业已调用。');
end;

procedure TForm1.Button16Click(Sender: TObject);
begin
  Workers.Post(MakeJobProc(DoGlobalJob), nil, True);
end;

procedure TForm1.Button17Click(Sender: TObject);
begin
  Workers.Post(SelfTerminateJob, 10000, nil, true);
end;

procedure TForm1.Button18Click(Sender: TObject);
var
  AId: Integer;
  T: Cardinal;
begin
  AId := Workers.RegisterSignal('Signal.SelfKill');
  Workers.Wait(SelfTerminateJob, AId, nil, True);
  Workers.Signal(AId);
  T := GetTickCount;
  while GetTickCount - T < 500 do
    Application.ProcessMessages;
  Workers.Signal(AId);
  T := GetTickCount;
  while GetTickCount - T < 500 do
    Application.ProcessMessages;
  Workers.Signal(AId);
  T := GetTickCount;
  while GetTickCount - T < 500 do
    Application.ProcessMessages;
  Workers.Signal(AId);
end;

procedure TForm1.Button19Click(Sender: TObject);
var
  AGroup: TQJobGroup;
  AMsg: string;
begin
  AGroup := TQJobGroup.Create(True);
  if AGroup.WaitFor() <> wrSignaled then
    AMsg := 'WaitFor空作业列表失败';
  AGroup.Prepare;
  AGroup.Add(DoNullJob, nil, false);
  AGroup.Add(DoNullJob, nil, false);
  AGroup.Add(DoNullJob, nil, false);
  AGroup.Run;
  if AGroup.WaitFor() <> wrSignaled then
    AMsg := 'WaitFor多个作业失败';
  FreeObject(AGroup);
  if Length(AMsg) > 0 then
    ShowMessage(AMsg)
  else
    ShowMessage('分组作业执行成功完成。');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Timer1Timer(Sender);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Workers.Post(DoPostJobDone, nil);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ShowMessage(IntToStr(GetTimeStamp));
end;

procedure TForm1.Button4Click(Sender: TObject);
const
  ACount: Integer = 10000000;
var
  I, ARuns: Integer;
  T1: Int64;
  ANeedRuns: Int64;
begin
  ARuns := 0;
//Workers.MaxWorkers:=500;
  ANeedRuns := ACount;
  T1 := GetTimeStamp;
  for I := 0 to ACount - 1 do
  begin
    assert(Workers.Post(DoJobProc, @ARuns), 'Post failure');
  end;
  while (ARuns < ANeedRuns) do
  {$IFDEF UNICODE}
    TThread.Yield;
  {$ELSE}
  SwitchToThread;
  {$ENDIF}
  T1 := GetTimeStamp - T1;
  ShowMessage('Time Used=' + IntToStr(T1) + ',Runs=' + IntToStr(ARuns) + ',Speed=' + IntToStr(Int64(ARuns) * 10000 div T1));
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  Workers.Post(DoMainThreadWork, nil, True);
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
  Workers.Signal('MySignal.Start');
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
  if not Workers.LongtimeJob(DoLongtimeWork, nil) then
    ShowMessage('长时间作业投寄失败');
end;

procedure TForm1.Button8Click(Sender: TObject);
begin
  ShowMessage('这个任务将在5秒后第一次启动,以后每隔1小时定时启动一次。');
  Workers.at(DoAtTimeJob1, 5 * QWorker.Q1Second, QWorker.Q1Hour, nil, True)
end;

procedure TForm1.Button9Click(Sender: TObject);
begin
  Workers.Delay(DoDelayJob, 5 * QWorker.Q1Second, nil, True)
end;

procedure TForm1.DoAtTimeJob1(AJob: PQJob);
begin
  ShowMessage('定时5秒后执行的任务已经执行了' + IntToStr(AJob.Runs + 1) + '次,1小时后执行下一次');
end;

procedure TForm1.DoAtTimeJob2(AJob: PQJob);
begin
  ShowMessage('定时任务已在' + FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now) + '开始第' + IntToStr(AJob.Runs + 1) + '次执行,1小时后执行下一次'#13#10 + '入队时间:' + IntToStr(AJob.PushTime) + #13#10 + '出队时间:' + IntToStr(AJob.PopTime));
end;

procedure TForm1.DoCancelJob(AJob: PQJob);
begin
  OutputDebugString(PWideChar('DoCancelJob(' + IntToHex(IntPtr(AJob), 8) + ')-' + IntToStr(Integer(AJob.Data)) + ' Started'));
  Sleep(5000);
  OutputDebugString(PWideChar('DoCancelJob(' + IntToHex(IntPtr(AJob), 8) + ')-' + IntToStr(Integer(AJob.Data)) + ' Finished'));
end;

procedure TForm1.DoCOMJob(AJob: PQJob);
var
  ADispatch: IDispatch;
begin
  AJob.Worker.ComNeeded();
  try
    ADispatch := CreateOleObject('ADODB.Recordset');
  except
  end;
end;

procedure TForm1.DoDelayJob(AJob: PQJob);
begin
  ShowMessage('延迟的任务已经执行完成了。'#13#10 + '入队时间:' + IntToStr(AJob.PushTime) + #13#10 + '出队时间:' + IntToStr(AJob.PopTime));
end;

procedure TForm1.DoJobProc(AJob: PQJob);
begin
  AtomicIncrement(PInteger(AJob.Data)^);
end;

procedure TForm1.DoLongtimeWork(AJob: PQJob);
begin
  while not AJob.IsTerminated do
  begin
    Sleep(1000);
    if AJob.EscapedTime > 50000 then//5s后结束任务,注意计时单位为0.1ms
      AJob.IsTerminated := True;
  end;
  if not Workers.Terminating then//如果未结束,则触发一个通知能前台,这样方便前台做一些进一步处理
    Workers.Signal('Longwork.Done');
end;

procedure TForm1.DoLongworkDone(AJob: PQJob);
begin
  ShowMessage('长时间作业已经完成');
end;

procedure TForm1.DoMainThreadWork(AJob: PQJob);
begin
  ShowMessage('这是在主线程中触发的异步作业。');
end;

procedure TForm1.DoNullJob(AJob: PQJob);
begin
  OutputDebugString('Null Job Executed');
end;

procedure TForm1.DoPostJobDone(AJob: PQJob);
begin
  PostMessage(Handle, WM_APP, AJob.PopTime - AJob.PushTime, 0);
end;

procedure TForm1.DoPostJobMsg(var AMsg: TMessage);
begin
  ShowMessage(Format('作业投寄到执行用时 %g ms', [AMsg.WParam / 10]));
end;

procedure TForm1.DoRandDelay(AJob: PQJob);
begin
  Label3.Caption := '随机作业末次延迟 ' + IntToStr((AJob.PopTime - AJob.PushTime) div 10) + 'ms';
  Workers.Delay(AJob.WorkerProc, qworker.Q1Second + random(qworker.Q1Second), AJob.Data, True);
end;

procedure TForm1.DoSignalJobMsg(var AMsg: TMessage);
begin
  Label2.Caption := Format('信号MySignal.Start已触发 %d次', [AMsg.WParam]);
end;

procedure TForm1.DoTimerJobMsg(var AMsg: TMessage);
begin
  Label1.Caption := '定时任务已执行' + IntToStr(AMsg.WParam) + '次';
end;

procedure TForm1.DoTimerProc(AJob: PQJob);
begin
  PostMessage(Handle, WM_APP + 2, AJob.Runs, 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutDown := True;
//注册一个信号触发函数,以便在触发时执行
  FSignalId := Workers.RegisterSignal('MySignal.Start');
  Workers.Wait(SignalWaitProc, FSignalId, nil);
//使用名称来触发的信号
  Workers.Wait(DoLongworkDone, Workers.RegisterSignal('Longwork.Done'), nil, true);
//注册一个定时执行任务信号,每0.1秒触发一次
  Workers.Post(DoTimerProc, 1000, nil);
  Caption := 'QWorker Demo (CPU:' + IntToStr(GetCpuCount) + ')';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Workers.Clear(Self);
end;

{ TAutoFreeTestObject }

constructor TAutoFreeTestObject.Create;
begin
  OutputDebugString('TAutoFreeTestObject.Create');
end;

destructor TAutoFreeTestObject.Destroy;
begin
  OutputDebugString('TAutoFreeTestObject.Free');
  inherited;
end;

end.

posted @ 2017-06-20 13:35  夏天的西瓜君  阅读(913)  评论(0编辑  收藏  举报