文档章节

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

涂孟超
 涂孟超
发布于 2014/09/26 15:35
字数 780
阅读 16
收藏 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

 
 
 
 
 

 

 

  

涂孟超
粉丝 13
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
用vertx实现高吞吐量的站点计数器

工具:vertx,redis,mongodb,log4j 源代码地址:https://github.com/jianglibo/visitrank 先看架构图: 如果你不熟悉vertx,请先google一下。我这里将vertx当作一个容器,上面所有的圆圈要...

jianglibo
2014/04/03
4.2K
3
CDH5: 使用parcels配置lzo

一、Parcel 部署步骤 1 下载: 首先需要下载 Parcel。下载完成后,Parcel 将驻留在 Cloudera Manager 主机的本地目录中。 2 分配: Parcel 下载后,将分配到群集中的所有主机上并解压缩。 3 激...

cloud-coder
2014/07/01
6.8K
1
Swift百万线程攻破单例(Singleton)模式

一、不安全的单例实现 在上一篇文章我们给出了单例的设计模式,直接给出了线程安全的实现方法。单例的实现有多种方法,如下面: class SwiftSingleton { } 这段代码的实现,在shared中进行条...

一叶博客
2014/06/20
3.5K
16
beego API开发以及自动化文档

beego API开发以及自动化文档 beego1.3版本已经在上个星期发布了,但是还是有很多人不了解如何来进行开发,也是在一步一步的测试中开发,期间QQ群里面很多人都问我如何开发,我的业余时间实在...

astaxie
2014/06/25
2.7W
22

没有更多内容

加载失败,请刷新页面

加载更多

【每周CV论文】初学深度学习图像对比度增强应该要读的文章

欢迎来到《每周CV论文》。在这个专栏里,还是本着有三AI一贯的原则,专注于让大家能够系统性完成学习,所以我们推荐的文章也必定是同一主题的。 图像对比度增强,即增强图像中的有用信息,抑...

言有三
昨天
0
0
运营商大数据-行业大数据获客利器

一、永远不要沉溺在安逸里得过且过,能给你遮风挡雨的,同样能让你不见天日,只有让自己更加强大,才能真正撑起一片天。 二、别把生活当作游戏,谁游戏人生,生活就惩罚谁,这不是劝诫,而是...

osc_1wo6kipk
25分钟前
0
0
【Rust日报】2020-08-10:在 Rust 中存储连续数据

在 Rust 中存储连续数据? 作者都帮你整理好了: 使用 Rust 中的数组 [T; N]. Slice &[T] or &mut [T], 可以方便的 split. Boxed slice Box<[T]>. Vec. 长度和内容都可以变化,这可能是我们最常...

MikeTang
昨天
19
0
Gradient Centralization: 一行代码加速训练并提升泛化能力 | ECCV 2020 Oral

梯度中心化GC对权值梯度进行零均值化,能够使得网络的训练更加稳定,并且能提高网络的泛化能力,算法思路简单,论文的理论分析十分充分,能够很好地解释GC的作用原理   来源:晓飞的算法工程...

zb1486966459725
昨天
0
0
移动大数据-装修行业获客利器

因为海伦凯勒的努力和坚毅不拔的个性,而赢得了大家的肯定,终于得到了诺贝尔文学奖。虽然得了诺贝尔奖,但她对生命依然奋战不懈,她马不停蹄的到各地学校里演讲。有一次,她到一所大学演讲,...

osc_qheq8wav
26分钟前
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部