Delphi定时器线程

UntMyTaskTimer.pas

//任务定时器--APC函数(异步过程调用)
//由于在调用APC函数时,SleepEx会锁死当前线程
//所以,需要创建单独的线程来处理


unit UntMyTaskTimer;

interface 

uses
  Windows, Messages, SysUtils, Variants, Classes;

type

  TTimerAPCProc = procedure(
  lpArgToCompletionRoutine: Pointer;
  dwTimerLowValue: DWORD;
  dwTimerHighValue: DWORD
  ); stdcall;

  TTimerThread = class(TThread)
  private
    thTimer: Cardinal;
    FDueTime: Int64;  //首次执行时间,单位:100纳秒

//起始时间(第二个参数)有三种赋值方法:
//1、> 0 时是绝对时间, 是一个 TFileTime 格式的时间(具体赋值方法后面详解);
//2、< 0 时是相对时间, 相对是相对于当前, 譬如 -50000000 表示 5 秒钟后执行(单位是0.1毫秒, 后面详述);
//3、= 0 时, 立即执行, 不再等待;


    FPeriod: Longint; //执行周期,单位:毫秒

//间隔时间(第三个参数)有两种情况:
//1、譬如 5000 表示每隔 5 秒钟执行一次, 其单位是毫秒; 本页第二个例子使用了 500(半秒);
//2、如果赋值为 0, 表示根据起始时间只执行一次, 不再重复执行.


    FTimes: Integer;      //执行次数

    FTimerAPCProc: TTimerAPCProc;

    FP: Pointer;  //FTimerAPCProc的第一个参数
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
                                   
    property DueTime: Int64 read FDueTime write FDueTime;
    property Period: Longint read FPeriod write FPeriod;
    property Times: Longint read FTimes write FTimes;
    property TimerAPCProc: TTimerAPCProc read FTimerAPCProc write FTimerAPCProc;
    property P: Pointer read FP write FP;
  end;  

const
  F1MILLISECOND = 10000;    //1毫秒内含10000个100纳秒

implementation


{ TTimerThread }

constructor TTimerThread.Create(CreateSuspended: Boolean);
begin
  thTimer:= CreateWaitableTimer(nil,False,nil);
  FDueTime:= 0;
  FPeriod:= 0;
  FTimes:= 0;
  inherited Create(true);
  FreeOnTerminate:= True;
end;

destructor TTimerThread.Destroy;
begin
  CloseHandle(thTimer);
  inherited;
end;

procedure TTimerThread.Execute;
var
  i: Integer;
begin
  inherited;
  SetWaitableTimer(thTimer,FDueTime,FPeriod,@FTimerAPCProc,FP,False);

  if FTimes=0 then
    SleepEx(INFINITE, True)
  else
  begin
    for i:= 0 to FTimes-1 do
      SleepEx(INFINITE, True);
  end;
end;

end.


引用方式:

var
  p: TPoint;

procedure TimerAPCProc2(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
  dwTimerHighValue: DWORD); stdcall;
var
  p:TPoint;
begin
  P:= PPoint(lpArgToCompletionRoutine)^;
  Form1.Canvas.TextOut(p.X,p.Y,FormatDateTime('yyyy-MM-dd HH:mm:ss.zzz',Now));
  form1.mmo1.Lines.Add('X:'+IntToStr(p.X)+';Y:'+IntToStr(p.Y));
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  t: TTimerThread;
begin
  t:= TTimerThread.Create(True);
  t.DueTime:= -20000000;
  t.TimerAPCProc:= TimerAPCProc2;
  P:= Point(X,Y);
  t.P:= @p;
  t.Resume;
end;
点击了窗体2秒之后,在点击的位置才会显示出当前时间。

还需要继续完善:在为APC函数传递参数时,需要将参数定义为全局变量,这样不好。应该在传递参数时从参数指针地址获取参数的值,保存到线程中。

参考文章:
多线程编程(14) - 多线程同步之 WaitableTimer (等待定时器对象)

CreateWaitableTimer和SetWaitableTimer函数(定时器)



猜你喜欢

转载自blog.csdn.net/liang08114/article/details/78840163