Delphi多线程编程(15)--多线程同步之WaitableTimer(等待定时器对象)[续]

转载自:万一的博客

 

  本次专门研究下 SetWaitableTimer的第二个参数(起始时间)

  它有正值、负值、0值这三种情况,前面已经用过 0 值

 


 

  先学习负值(相对时间),也就是从当前算起隔多长时间开始执行

  这个相对时间是以 1/100 纳秒为单位的,譬如赋值:3*10000000 相当于 3 秒

1 s(秒) = 1,000             ms(毫秒);
1 s(秒) = 1,000,000         µs(微妙);
1 s(秒) = 1,000,000,000     ns(纳秒);
1 s(秒) = 1,000,000,000,000 ps(皮秒);

  本例的效果图

技术分享

  代码文件

unit Unit1;
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  f: Integer;
  hWaitableTimer: THandle;

function MyThreadFun(p: Pointer): DWORD; stdcall;
var
  i, y: Integer;
  y:= 20* f;

  if WaitForSingleObject(hWaitableTimer, INFINITE)=WAIT_OBJECT_0 then
  begin
    for i:= 0 to 1000 do
    begin
      Form1.Canvas.Lock;
      Form1.Canvas.TextOut(20, y, IntToStr(i));
      Form1.Canvas.UnLock;
      Sleep(1);
    end;
  end;
  Result:= 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ThreadID: DWORD;
  DueTime: Int64;
begin
  hWaitableTimer:= CreateWaitableTimer(nil, True, nil);
  DueTime:= -3*10000000;    //3秒钟之后执行
  SetWaitableTimer(hWaitableTimer, DueTime, 0, nil, nil, False);
    
  Repaint; f:= 0;
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CloseHandle(hWaitableTimer);
end;

end.

  窗体文件

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = ‘Form1‘
  ClientHeight = 116
  ClientWidth = 179
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = ‘Tahoma‘
  Font.Style = []
  OldCreateOrder = False
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 96
    Top = 83
    Width = 75
    Height = 25
    Caption = ‘Button1‘
    TabOrder = 0
    OnClick = Button1Click
  end
end

  


  当我们需要一个绝对时间,譬如 2009-2-18 13:10:5,函数需要的Int64 值应该是 TFileTime格式的时间

  先看三种相关时间类型(TFileTime、TSystemTime、TDateTime)的定义

//TFileTime 又名 FILETIME或_FILETIME
_FILETIME = record
    dwLowDateTime: DWORD;
    dwHighDateTime: DWORD;
end;

//TSystemTime 又名 SYTEMTIME 或 _SYSTEMTIME
_SYSTEMTIME=record
    wYear: Word;
    wMonth: Word;
    wDayOfWeek: Word;
    wDay: Word;
    wHour: Word;
    wMinute: Word;
    wSecond: Word;
    wMilliseconds: Word;
end;

TDateTime= type Double;

  TFileTime 相当于一个Int64, 一般要通过 TSystemTime 或TDateTime 赋值,然后转换过去

  在例子中,我是通过下面过程转换过去的:

StrToDateTime->DateTimeToSystemTime->SystemTimeToFileTime->LocalFileTimeToFileTime

 


  下面程序执行在2009年2月18号下午1点10分5秒时运行三个线程(窗体同上,我已经找到了合适的时间测试成功)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  f: Integer;
  hWaitableTimer: THandle;

function MyThreadFun(p: Pointer): DWORD; stdcall;
var
  i,y: Integer;
begin
  Inc(f);
  y := 20 * f;

  if WaitForSingleObject(hWaitableTimer, INFINITE) = WAIT_OBJECT_0 then
  begin
    for i := 0 to 1000 do
    begin
      Form1.Canvas.Lock;
      Form1.Canvas.TextOut(20, y, IntToStr(i));
      Form1.Canvas.Unlock;
      Sleep(1);
    end;
  end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  strTime = ‘2009-2-18 13:10:5‘;
var
  ThreadID: DWORD;
  DueTime: Int64;
  st: TSystemTime;
  ft,UTC: TFileTime;
  dt: TDateTime;
begin
  DateTimeToSystemTime(StrToDateTime(strTime), st); {从 TDateTime 到 TSystemTime}
  SystemTimeToFileTime(st, ft);                     {从 TSystemTime 到 TFileTime}
  LocalFileTimeToFileTime(ft, UTC);                 {从本地时间到国际标准时间 UTC}
  DueTime := Int64(UTC);                            {函数需要的是 Int64}

  hWaitableTimer := CreateWaitableTimer(nil, True, nil);
  SetWaitableTimer(hWaitableTimer, DueTime, 0, nil, nil, False);

  Repaint; f := 0;
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  CloseHandle(hWaitableTimer);
end;

end.

  


  接下来该是WaitableTimer 对象的回调函数了

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。