文档章节

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

涂孟超
 涂孟超
发布于 2014/09/26 15:35
字数 780
阅读 14
收藏 0

根据 WaitableTimer 的主要功用, 现在再把它放在 "线程同步" 的话题中讨论有点不合适了, 就要结束它.

//重新看看那个 APC 回调函数的格式:
procedure TimerAPCProc(
  lpArgToCompletionRoutine: Pointer;
  dwTimerLowValue, dwTimerHighValue: DWORD
); stdcall;

 
 
 
 
 

 

 

  

TimerAPCProc 的后两个参数其实是在传递一个值, 使用时要把它们合并为一个 TFileTime 类型的时间.
这个时间是 APC 函数被调用的时间, 稍稍修改上面一个例子看一下:



代码文件:
unit Unit1;

interface

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

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  hTimer: THandle;

{APC 函数}
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
  dwTimerHighValue: DWORD); stdcall;
var
  UTCFileTime,LocalFileTime: TFileTime;
  SystemTime: TSystemTime;
  DateTime: TDateTime;
begin
  {把 dwTimerLowValue 与 dwTimerHighValue 和并为一个 TFileTime 格式的时间}
  UTCFileTime.dwLowDateTime := dwTimerLowValue;
  UTCFileTime.dwHighDateTime := dwTimerHighValue;

  FileTimeToLocalFileTime(UTCFileTime, LocalFileTime); {从世界标准计时到本地时间}
  FileTimeToSystemTime(LocalFileTime, SystemTime);     {转到系统格式时间}
  DateTime := SystemTimeToDateTime(SystemTime);        {再转到 TDateTime}

  Form1.Text := DateTimeToStr(DateTime);
  SleepEx(INFINITE, True);
end;

{线程入口函数}
function MyThreadFun(p: Pointer): Integer; stdcall;
var
  DueTime: Int64;
begin
  DueTime := 0;
  if SetWaitableTimer(hTimer, DueTime, 1000, @TimerAPCProc, nil, False) then
  begin
    SleepEx(INFINITE, True);
  end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ID: DWORD;
begin
  if hTimer = 0 then  hTimer := CreateWaitableTimer(nil, True, nil);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  CancelWaitableTimer(hTimer);
end;

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

end.

 
 
 
 
 

 

 

  

窗体文件:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 86
  ClientWidth = 256
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 23
    Top = 32
    Width = 97
    Height = 25
    Caption = #21551#21160#23450#26102#22120
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 134
    Top = 32
    Width = 97
    Height = 25
    Caption = #21462#28040#23450#26102#22120
    TabOrder = 1
    OnClick = Button2Click
  end
end

 
 
 
 
 

 

 

  

SetWaitableTimer 中回调函数后面的指针参数, 将被传递给 APC 函数的第一个参数;
作为指针它可以携带任何数据, 这里让它携带了一个坐标点(鼠标点击窗体的位置), 下例效果图:



代码文件:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    procedure FormDestroy(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  hTimer: THandle;
  pt: TPoint;

{APC 函数}
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
  dwTimerHighValue: DWORD); stdcall;
var
  UTCFileTime,LocalFileTime: TFileTime;
  SystemTime: TSystemTime;
  DateTime: TDateTime;
  pt2: TPoint;
begin
  UTCFileTime.dwLowDateTime := dwTimerLowValue;
  UTCFileTime.dwHighDateTime := dwTimerHighValue;

  FileTimeToLocalFileTime(UTCFileTime, LocalFileTime);
  FileTimeToSystemTime(LocalFileTime, SystemTime);
  DateTime := SystemTimeToDateTime(SystemTime);

  pt2 := PPoint(lpArgToCompletionRoutine)^; {接受指针参数}
  Form1.Canvas.Lock;
  Form1.Canvas.TextOut(pt2.X, pt2.Y, DateTimeToStr(DateTime));
  Form1.Canvas.Unlock;

  SleepEx(INFINITE, True);
end;

{线程入口函数}
function MyThreadFun(p: Pointer): Integer; stdcall;
var
  DueTime: Int64;
begin
  DueTime := 0;
  {参数 @pt 在这里是鼠标点击窗体时的坐标结构的指针, 它将传递给 APC 函数的第一个参数}
  if SetWaitableTimer(hTimer, DueTime, 1000, @TimerAPCProc, @pt, False) then
  begin
    SleepEx(INFINITE, True);
  end;
  Result := 0;
end;

{建立 WaitableTimer 对象和线程}
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  ID: DWORD;
begin
  pt := Point(X,Y); {在这里个全局的坐标点赋值}
  if hTimer = 0 then  hTimer := CreateWaitableTimer(nil, True, nil);
  CreateThread(nil, 0, @MyThreadFun, nil, 0, ID);
end;

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

end.

 
 
 
 
 

 

 

  

窗体文件:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 135
  ClientWidth = 195
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnMouseDown = FormMouseDown
  PixelsPerInch = 96
  TextHeight = 13
end

 
 
 
 
 

 

 

  

本文转载自:http://www.cnblogs.com/del/archive/2009/02/19/1393835.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
《Java多线程编程核心技术》读书笔记

《Java多线程编程核心技术》读书笔记。 第一章 Java多线程技能 使用Java多线程两种方式。 继承Thread类与实现Runnable接口。 线程的开始、中止、暂停、恢复、停止。 、、、、 线程的、、优先...

刀狂剑痴
2016/05/02
390
0
C#多线程学习(三) 生产者和消费者

[1] C#多线程学习(三) 生产者和消费者 [2]C#多线程学习(三) 生产者和消费者 本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者...

Yamazaki
2012/03/29
0
0
C#多线程学习(六) 互斥对象

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线...

Yamazaki
2012/03/29
0
0
boost------asio库的使用1(Boost程序库完全开发指南)读书笔记

asio库基于操作系统提供的异步机制,采用前摄器设计模式(Proactor)实现了可移植的异步(或者同步)IO操作,而且并不要求多线程和锁定,有效地避免了多线程编程带来的诸多有害副作用。 目前asi...

LUIS1983
2016/12/23
30
0
delphi之多线程编程(一)

delphi之多线程编程(一) 本文的内容取自网络,并重新加以整理,在此留存仅仅是方便自己学习和查阅。所有代码均亲自测试 delphi7下测试有效。图片均为自己制作。 多线程应该是编程工作者的基础...

KavenSu
2014/01/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

多线程

1. 多线程概念。并发和并行的概念。 多线程指的是一段时间内cpu同时执行多个线程。一个程序至少运行>=1个进程,进程就是运行中的程序,而一个进程至少运行>=1个线程,线程是操作系统能调度的...

鱼想吃肉
38分钟前
0
0
HBase 表修复在线方式和离线方式

一、在线修复 1.1 使用检查命令 $ ./bin/hbase hbck 该命令可完整修复 HBase 元数据信息;存在有错误信息会进行输出; 也可以通过如下命令查看详细信息: $ ./bin/hbase hbck -details 1.2 ...

Ryan-瑞恩
今天
2
0
redis 系列二 -- 常用命令

1.基础命令 info ping quit save dbsize select flushdb flushall 2.键命令 2.1 set 直接赋值 set a a 2.2 get 取值 get a 2.3 exists 是否存在 exists a 2.4 expire 设置剩余时间 秒 expire......

imbiao
今天
2
0
php foreach

<?php// 数组的引用$a=array(1,2,3,4,5);foreach($a as $key=>&$value){$value=$value*2;}print_r($a);echo " $key -------------------$value\r\n";/** * ...

小张525
今天
3
0
12-利用思维导图梳理JavaSE-多线程

12-利用思维导图梳理JavaSE-多线程 主要内容 1.线程概念 2.线程开发 3.线程的状态 4.线程的同步和死锁 5.Java5.0并发库类 QQ/知识星球/个人WeChat/公众号二维码 本文为原创文章,如果对你有一...

飞鱼说编程
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部