进程与线程(五)用内核对象进行线程同步(上)

来源:互联网 发布:广州淘宝二手车网 编辑:程序博客网 时间:2024/05/18 02:31
当系统初始化一个内核对象时,会将其结构内部的一个变量初始化为FALSE,也就是未触发状态。线程可以等待一个内核对象,进入等待状态,当这个内核对象变为TURE的触发状态时,唤醒线程。

线程内核对象在线程初始化时设置为未触发,当线程结束时设置为触发,所以我们可以用WaitForSingleObject来等待一个线程的结束,CreateEvent可以创建一个事件内核对象,可以用来进行同步。


 1 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])   2 {   3     _tsetlocale(LC_ALL,_T("chs") );   4     system("title ReturnsMe的win32api测试程序");    5     //创建一个事件内核对象  6     g_hevent = CreateEvent(NULL,FALSE,FALSE,_T("event"));   7   8     chBEGINTHREADEX(NULL,NULL,PrintThread,NULL,0,NULL);   9     HANDLE h = chBEGINTHREADEX(NULL,NULL,SetThread,NULL,0,NULL);  10      11     WaitForSingleObject(h,INFINITE);  12  13     system("pause");  14     return 0;  15 }  16 DWORD WINAPI SetThread(PVOID pvParam)  17 {  18     for (int i =0;i<=100;i++)  19     {  20         g_num = g_num +i;  21     }  22     wprintf(_T("SetThread:g_num is %d \n"),g_num);  23     Sleep(2000);  24     SetEvent(g_hevent);  //设置内核对象为触发状态 25     return 0;  26 }  27  28 DWORD WINAPI PrintThread(PVOID pvParam)  29 {  30     WaitForSingleObject(g_hevent,INFINITE);  31     wprintf(_T("PrintThread:g_num is %d \n"),g_num);  32     return 0;  33 }除了事件内核对象以外,还有计时器,信号量,互斥量等等内核对象可以用来线程同步,未完待续....update:计时器允许我们在特定时间触发一个内核对象,并且可以每隔一段时间触发一次。下面是一个例子,注释很详细。  1 HANDLE g_htimer;   2   3 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])   4 {   5     _tsetlocale(LC_ALL,_T("chs") );   6     system("title ReturnsMe的win32api测试程序");     7   8     //设置一个手动重置的内核对象,如果我们没有从外部调用这个计时器的需求,我们可以给名字传一个NULL   9     g_htimer  = CreateWaitableTimer(NULL,FALSE,NULL);  10  11     FILETIME ftLocal,ftUTC,ftNewUTC;  12     SYSTEMTIME st;  13       14     //得到当前UTC时间,FILETIME格式  15     ftUTC = CFileTime::GetCurrentTime();  16     //时区换算  17     FileTimeToLocalFileTime(&ftUTC,&ftLocal);  18     //转换成系统时间  19     FileTimeToSystemTime(&ftLocal,&st);  20  21     wprintf(_T("time is %d:%d:%d \n" ),st.wHour,st.wMinute,st.wSecond);  22       23     //即时时间加两秒,然后转换成FILETIME格式的UTC时间  24     st.wSecond = st.wSecond +2;  25  26     SystemTimeToFileTime(&st,&ftLocal);  27     LocalFileTimeToFileTime(&ftLocal,&ftNewUTC);  28  29     //这么做是为了兼容x64cpu,对齐地址  30     LARGE_INTEGER li;  31     li.HighPart = ftNewUTC.dwHighDateTime;  32     li.LowPart = ftNewUTC.dwLowDateTime;  33  34     //设置计时器,第二个参数传入绝对时间,也就是刚才得到的CFileTime::GetCurrentTime();的2s后  35     //第一次设置计时器为触发状态,以后每5s触发一次  36     SetWaitableTimer(g_htimer,&li,5000,NULL,NULL,FALSE);  37     HANDLE h = chBEGINTHREADEX(NULL,NULL,PrintThread,NULL,0,NULL);   38  39     WaitForSingleObject(h,1000*60);  40  41     system("pause");  42     return 0;  43 }  44 DWORD WINAPI PrintThread(PVOID pvParam)  45 {  46  47     for (int i=0;i<=5;i++)  48     {  49         //循环等待,打印6次后退出线程  50         WaitForSingleObject(g_htimer,INFINITE);  51         wprintf(_T("this is the %dth time to call wprintf \n"),i+1);  52     }  53  54     //用完了就做掉它,=。=|||  55     CancelWaitableTimer(g_htimer);  56  57     return 0;  58 }  59当然set函数也可以设置一个相对时间,而且也允许插入一个时间的apcHANDLE g_htimer; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { _tsetlocale(LC_ALL,_T("chs") ); system("title ReturnsMe的win32api测试程序");   AccessTimerAndAPC(); system("pause"); return 0; } VOID AccessTimerAndAPC() { g_htimer = CreateWaitableTimer(NULL,TRUE,NULL); FILETIME ftUTC,ftLocal; SYSTEMTIME st; ftUTC = CFileTime::GetCurrentTime(); FileTimeToLocalFileTime(&ftUTC,&ftLocal); FileTimeToSystemTime(&ftLocal,&st); //上次是绝对时间,这次用相对时间,传给apc一个创建时间 LARGE_INTEGER li={0}; SetWaitableTimer(g_htimer,&li,1000,APCRoutine,(LPVOID)&st,FALSE); //当且仅当函数处于一个alertable state时,系统才会把计时器的APC函数添加到列队之中 SleepEx(INFINITE,TRUE); } VOID WINAPI APCRoutine(LPVOID lpArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue) { PSYSTEMTIME pst = (PSYSTEMTIME)lpArgToCompletionRoutine; wprintf(_T("apc is inserted to the routine at %d:%d:%d \n"),pst->wHour,pst->wMinute,pst->wSecond); Sleep(2000); FILETIME ftUTC,ftLocal; ftUTC = CFileTime::GetCurrentTime(); FileTimeToLocalFileTime(&ftUTC,&ftLocal); FileTimeToSystemTime(&ftLocal,pst); wprintf(_T("it's  %d:%d:%d  now \n"),pst->wHour,pst->wMinute,pst->wSecond); }


原创粉丝点击