您的位置:首页 > 其它

线程同步——内核对象实现线程同步——可等待计时器内核对象

2014-08-16 11:08 381 查看
  1 可等待计时器
可等待计时器是这样一种内核对象,他们会在某个指定的时间触发或每隔一段时间触发一次。
下面我们来介绍一下创建可等待计时器函数:

HANDLE CreateWaitableTimer(
LPSECURITY_ATTRIBUTES lpTimerAttributes,
BOOL bManualReset,
LPCSTR lpTimerName );
第一、三个参数我想我也不用介绍了哈,这是创建内核对象基本都会有的参数。
第二个参数bManualReset表示是创建一个手动重置(TRUE),还是自动重置(FALSE)计时器。
有一点需要记住:创建可等待计时器总是处于未触发状态。必须调用SetWaitableTimer函数来告诉它。

BOOL SetWaitableTimer(
HANDLE hTimer,
const LARGE_INTEGER *lpDueTime,
LONG lPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine,
LPVOID lpArgToCompletionRoutine,
BOOL fResume );
第一参数hTimer表示我们要设置的计时器
第二个和第三个参数应该一起使用,lpDueTime表示第一次触发应该在什么时候,
lPeriod表示计时器应该以什么样的频度触发。第三个参数的单位是微秒
另外两个参数这里就先不介绍了,如果感兴趣可以阅读《windows核心编程(第五版)》245页 或者参考MSDN.
如果只是简单的应用,后面三个参数,依次填入 NULL,NULL,FALSE 即可,嘿嘿,简单吧!

特别注意:
如果该计时器是手动重置,则正在等待该线程的所有线程变为可调度,当该定时器是自动重置,
则只有一个等待该线程的计时器变为可调度。当定时器是自动重置时,每当WaitFor*Object
获得该对象时,会重新计时,而手动重置则不会重新计时,这点特别注意。

下面说一下使用步骤
1)
//定义一个定时器内核对象,还有一些关于时间的变量
HANDLE g_hTimer ;
SYSTEMTIME st;

FILETIME ftLocal,ftUTC;

LARGE_INTEGER liUTC ;
2)
//创建一个自动重置的定时器内核对象
g_hTimer = CreateWaitableTimer(NULL,FALSE,NULL);

3)设置定时器内核对象,时间可以更根据自己的实际情况设定
//第一次响应是在 2014.08.10  在 17:12分

st.wYear = 2014 ;
st.wMonth = 8 ;
//st.wDayOfWeek = 0  //可以忽悠
st.wDay = 10 ;
st.wHour = 17 ;
st.wMinute = 12;
st.wSecond = 0 ;
st.wMilliseconds = 0 ;

SystemTimeToFileTime(&st,&ftLocal);

LocalFileTimeToFileTime(&ftLocal,&ftUTC) ;

liUTC.LowPart = ftUTC.dwLowDateTime ;
liUTC.HighPart = ftUTC.dwHighDateTime ;

//每隔1秒钟响应依次,记住,第三个单位是微妙,这里容易使人忘记。
SetWaitableTimer(g_hTimer,&liUTC,1000,NULL,NULL,FALSE);

4)在线程函数中调用
DWORD WINAPI ThreadFunOne(PVOID pvParam)
{
while(1)
{
WaitForSingleObject(g_hTimer,INFINITE);
g_x++;
cout<<"我是ThreadFunOne:"<<g_x<<endl;
}
return 0;
}

#include "windows.h"
#include "iostream"
using namespace std;
long g_x = 0 ;

//定义一个定时器内核对象,还有一些关于时间的变量
HANDLE g_hTimer ;
SYSTEMTIME st;

FILETIME ftLocal,ftUTC;

LARGE_INTEGER liUTC ;

//定义线程函数1
DWORD WINAPI ThreadFunOne(PVOID pvParam) ;

//定义线程函数2
DWORD WINAPI ThreadFunTwo(PVOID pvParam);

int main()
{

//创建一个自动重置的定时器内核对象
g_hTimer = CreateWaitableTimer(NULL,FALSE,NULL);

//第一次响应是在 2014.08.10  在 17:12分

st.wYear = 2014 ;
st.wMonth = 8 ;
//st.wDayOfWeek =
st.wDay = 10 ;
st.wHour = 17 ;
st.wMinute = 12;
st.wSecond = 0 ;
st.wMilliseconds = 0 ;

SystemTimeToFileTime(&st,&ftLocal);

LocalFileTimeToFileTime(&ftLocal,&ftUTC) ;

liUTC.LowPart = ftUTC.dwLowDateTime ;
liUTC.HighPart = ftUTC.dwHighDateTime ;

SetWaitableTimer(g_hTimer,&liUTC,1000,NULL,NULL,FALSE);

//创建线程1
HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL);
CloseHandle(hThreadOne);

//创建线程2
HANDLE hThreadTwo = CreateThread(NULL,0,ThreadFunTwo,0,0,NULL);
CloseHandle(hThreadTwo);

//让主线程先挂起,确保其它线程执行完成

getchar();
cout<<g_x<<endl;
return 0 ;
}

DWORD WINAPI ThreadFunOne(PVOID pvParam)
{
while(1)
{
WaitForSingleObject(g_hTimer,INFINITE);
g_x++;
cout<<"我是ThreadFunOne:"<<g_x<<endl;
}
return 0;
}

DWORD WINAPI ThreadFunTwo(PVOID pvParam)
{
while (1)
{
WaitForSingleObject(g_hTimer,INFINITE);
g_x++;
cout<<"我是ThreadFunTwo:"<<g_x<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: