windows笔记-【内核对象线程同步】等待定时器内核对象

等待定时器 是在某个时间或按规定的间隔时间发出自己的信号通知的内核对象。它们通常用来在某个时间执行某个操作。

创建等待定时器

HANDLE CreateWaitableTimer (

   PSECURITY_ATTRIBUTES psa,

   BOOL fManualReset,

   PCTSTR pszName

);

psa pszName 这两个参数(见内核对象的安全性  和 跨越进程边界共享内核对象【命名对象】

fManualReset 参数 用于指明人工重置的定时器或自动重置的定时器。(与事件的情况一样。见【内核对象线程同步】事件内核对象

人工重置 的定时器信号通知时,等待该定时器的所有 线程均变为可调度线程。

自动重置 的定时器信号通知时,只有一个等待 的线程变为可调度线程。

 

进程可以获得它自己的与进程相关的现有等待定时器的句柄,方法是调用 OpenWaitableTimer 函数: (见:跨越进程边界共享内核对象【命名对象】 :: 按名字共享对象的另一种方法)

HANDLE OpenWaitableTimer (

   DWORD dwDesiredAccess,

   BOOL bInheritHandle,

   PCTSTR pszName

);

等待定时器对象总是在未通知状态中创建 ( 不像事件对象那样,可以让我们指定 )

 

SetWaitableTimer 函数告诉定时器你想在何时让它成为已通知状态

BOOL SetWaitableTimer (

   HANDLE hTimer,

   const LARGE_INTEGER *pDueTime,

   LONG lPeriod,

   PTIMERAPCROUTINE pfnCompletionRoutine,

   PVOID pvArgToCompletionRoutine,

   BOOL fResume

);

hTimer 参数 用于指明你要设置的定时器。

pDueTime lPeriod 两个参数是一道使用的。 PDueTimer 参数 用于指明定时器何时应该第一次报时,而 lPeriod 参数 则用于指明此后定时器应该间隔多长时间报时一次。

 

例子

下面的代码用于将定时器的第一次报时的时间设置在 2002 1 1 日的下午 1 点钟,然后每隔 6 小时报时一次:

// Declare our local variables.

HANDLE hTimer;

SYSTEMTIME st;

FILETIME ftLocal, ftUTC;

LARGE_INTEGER liUTC;

 

// Create an auto-reset timer.

hTimer = CreateWaitableTimer (NULL, FALSE, NULL);

 

// First signaling is at January 1, 2002, at 1:00 P.M. (local time).

st.wYear         = 2002; // Year

st.wMonth        = 1;    // January

st.wDayOfWeek    = 0;    // Ignored

st.wDay          = 1;    // The first of the month

st.wHour         = 13;   // 1PM

st.wMinute        = 0;    // 0 minutes into the hour

st.wSecond       = 0;    // 0 seconds into the minute

st.wMilliseconds = 0;    // 0 milliseconds into the second

 

SystemTimeToFileTime (&st, &ftLocal);

 

// Convert local time to UTC time.

LocalFileTimeToFileTime (&ftLocal, &ftUTC);

// Convert FILETIME to LARGE_INTEGER because of different alignment.

liUTC.LowPart  = ftUTC.dwLowDateTime;

liUTC.HighPart = ftUTC.dwHighDateTime;

 

// Set the timer.

SetWaitableTimer (hTimer, &liUTC,   6 * 60 * 60 * 1000,   NULL,   NULL,   FALSE);

...

代码首先对 SYSTEMTIME 结构进行初始化,该结构用于指明定时器何时第一次报时(发出信号通知)。将该时间设置为本地时间,即计算机所在时区的正确时间。 SetWaitableTimer 的第二个参数的原型是个常量 LARGE_INTEGER * ,因此它不能直接接受 SYSTEMTIME 结构。但是, FILETIME 结构和 LARGE_INTEGER 结构 拥有相同的二进制格式,都包含两个 32 位的值。因此,我们可以将 SYSTETIME 结构转换成 FILETIME 结构。再一个问题是, SetWaitableTimer 希望传递给它的时间始终都采用世界协调时( UTC )的时间。调用 LocalFileTimeToFileTime 函数,就可以很容易地进行时间的转换。

现在,若要使定时器在 2002 1 1 日下午 1 点之后每隔 6 h 进行一次报时,我们应该将注意力转向 lPeriod 参数。该参数用于指明定时器在初次报时后每隔多长时间(以毫秒为单位 )进行一次报时。如果是每隔 6h 进行一次报时,那么我传递 21600000 6 h× 每小时 60min× 每分钟 60s× 每秒 1000 ms )。另外,如果给它传递了以前的一个绝对时间,比如 1 9 7 5 1 1 日下午 1 点,那么 SetWaitableTimer 的运行就不会失败。


让定时器在一个相对于调用 SetWaitableTimer 的时间进行报时 代码下载

只需要在 pDueTime 参数中传递一个负值传递的值必须是以 100ns 为间隔。 由于我们通常并不以 100ns 的间隔来思考问题,因此我们要说明一下 100ns 的具体概念: 1s = 1000ms = 1000000µs = 100 000000ns

  
  
g_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);

const int nTimerUnitsPerSecond = 10000000 ;
LARGE_INTEGER li;
li.QuadPart
= - ( 3 * nTimerUnitsPerSecond);
SetWaitableTimer(g_hTimer,
& li, 1000 , NULL, NULL, FALSE);

 

 


通常情况下,你可能想要一个一次报时的定时器 ,它只是发出一次报时信号,此后再也不发出报时信号。若要做到这一点,只需要为 lPeriod 参数传递 0 即可 。然后可以调用 CloseHandle 函数,关闭定时器 ,或者再次调用 SetWaitableTimer 函数,重新设置时间,为它规定一个需要遵循的新条件。

参数是 fResume ,它可以用于支持暂停和恢复 的计算机。通常可以为该参数传递 FALSE ,就像我在上面这个代码段中设置的那样。但是,如果你编写了一个会议安排类型的应用程序,在这个应用程序在中,你想设置一个为用户提醒会议时间安排的定时器,那么应该传递 TRUE 当定时器报时的时候,它将使计算机摆脱暂停方式(如果它处于暂停状态的话),并唤醒等待定时器报时的线程。然后该应用程序运行一个波形文件,并显示一个消息框,告诉用户即将举行的会议。如果为 fResume 参数传递 FALSE 定时器对象就变为已通知状态,但是它唤醒的线程必须等到计算机恢复运行(通常由用户将它唤醒)之后才能得到 CPU 时间。 ( 还不是很明白 , 暂停计算机是什么意思,进入睡眠吗?

 

BOOL CancelWaitableTimer (HANDLE hTimer);

这个简单的函数用于取出定时器的句柄并将它撤消,这样,除非接着调用 SetWaitableTi mer 数以便重新设置定时器,否则定时器决不会进行报时。如果想要改变定时器的报时条件, 不必在调用 SetWaitableTimer 函数之前调用 CancelWaitableTimer 函数。每次调用 SetWaitableTier 函数,都会在设置新的报时条件之前撤消定时器原来的报时条件。

 

本文地址:http://www.cnblogs.com/fangyukuan/archive/2010/09/05/1818293.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值