[教程]基于 QWorker 的多线程编程 – 计划任务

如果前面的各种设置无法满足你的要求,你可能需要的是计划任务。QWorker 支持 Linux 的 Cron 计划任务配置文件格式,可以直接调用 Plan 函数来传递格式字符串到程序中进行任务调度。

与普通的作业不同,计划的作业任务分辨率比较粗,与 Linux Cron 配置文件格式一样精确到分钟。

QWorker 支持的 Linux 的 Cron 格式说明:

分 时 日 月 周 命令

如果某一位置值为“*”,则代表忽略这一条件,只要其它条件符合就执行;

支持 n-n 格式的范围,如 3-6 代表从 3 到 6;

支持间隔设置,格式为/n,如/2;

同一位置的多个时间值之间可以用 “,” 直接分隔。

周后面的命令不支持换行,后面所有内容直接被当做命令保存下来,赋给 TQPlanMask.Content 成员。

下面是几个例子:

  1. 每分钟执行一次: * * * * *
  2. 每小时 5 分执行一次:5 * * * *
  3. 每个月 1 号 23:00 执行一次:0 23 1 * *
  4. 每周一晚上 23:00 执行一次:0 23 * * 1
  5. 每小时的 30-40 分钟,每隔两分钟执行一次:30-40/2 * * * *
  6. 每小时的 10 分和 35 分各执行一次: 10,35 * * * *

QDAC 对命令格式的检查进行了一些较宽容的处理,如下面的格式也认为是合适的值:

3 这是计划任务

上面创建的是每小时的3分执行的计划任务。也就是说,遇到无效的字符就认为是命令的开始。

现在看下QWorker 的 Plan 函数声明:

【Delphi】

function Plan(AProc: TQJobProc; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

function Plan(AProc: TQJobProc; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

function Plan(AProc: TQJobProcG; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

function Plan(AProc: TQJobProcG; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

function Plan(AProc: TQJobProcA; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

function Plan(AProc: TQJobProcA; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;

【C++】

NativeInt __fastcall Plan(TQJobProc AProc, const Qtimetypes::TQPlanMask &APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

NativeInt __fastcall Plan(TQJobProc AProc, const System::UnicodeString APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

NativeInt __fastcall Plan(TQJobProcG AProc, const Qtimetypes::TQPlanMask &APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

NativeInt __fastcall Plan(TQJobProcG AProc, const System::UnicodeString APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

NativeInt __fastcall Plan(_di_TQJobProcA AProc, const Qtimetypes::TQPlanMask &APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

NativeInt __fastcall Plan(_di_TQJobProcA AProc, const System::UnicodeString APlan, void * AData, bool ARunInMainThread = false, TQJobDataFreeType AFreeType = (TQJobDataFreeType)(0x0))/* overload */;

其中的 APlan 参数可以是 TQPlanMask 或者是 Linux Cron 兼容的计划任务字符串,内部自动解析处理。至于其它参数和普通的 Post 作业完全一样,也不就再解释。
【Delphi】

Workers.Plan(DoPlanJob,TQPlanMask.Create('* * * * * 1 Minute Plan Job'),nil,true);

【C++】

Workers->Plan(DoPlanJob,TQPlanMask.Create(L"* * * * * 1 Minute Plan Job"),NULL,true);

【Delphi】

Workers.Plan(DoPlanJob,'* * * * * 1 Minute Plan Job',nil,true);

【C++】

Workers->Plan(DoPlanJob,"* * * * * 1 Minute Plan Job",NULL,true);

用到的 DoPlanJob 函数:

【Delphi】

procedure TForm1.DoPlanJob(AJob: PQJob);
var
  APlan:PQJob;
begin
APlan:=AJob.PlanJob;
lblPlanStatic.Caption:='计划任务已执行'+IntToStr(AJob.Runs+1)+'次'#13#10+'内容:'+APlan.ExtData.AsPlan.Plan.Content;
end;

【C++】

void __fastcall TForm1::DoPlanJob(PQJob AJob);
{
PQJob APlan=PQJob(AJob.PlanJob);
lblPlanStatic->Caption=L"计划任务已执行"+IntToStr(AJob.Runs+1)+L"次\r\n内容:'+APlan->ExtData->AsPlan->Plan->Content;
}

 

效果是完全等价的两个调用,实际执行效果:

QWorkerPlan

 

 

分享到: