示例
#define UNICODE #include <stdio.h> #include <tchar.h> #include <windows.h> #include <process.h> #define ___tmainCRTStartup int *gPNum; BOOL gUsing = FALSE; void Entry() { while(InterlockedExchange((long*)&gUsing,TRUE) == TRUE) { Sleep(0); } } void Leave() { InterlockedExchange((long*)&gUsing, FALSE); } void ThreadPrint(TCHAR* strText) { Entry(); _tprintf(strText); Leave(); } unsigned __stdcall StartThread(void* lParam) { ThreadPrint("StarThread Beging.......\r\n"); gPNum = new int(0); Sleep(1000); ThreadPrint("StarThread End.......\r\n"); return 0; } unsigned __stdcall EndThread(void* lParam) { ThreadPrint("EndThread Beging.......\r\n"); HANDLE hStart = lParam; WaitForSingleObject(hStart, INFINITE); delete gPNum; ThreadPrint("EndThread End.......\r\n"); return 0; } int main() { HANDLE hStart = (HANDLE)_beginthreadex(nullptr, 0, StartThread, nullptr, 0, nullptr); HANDLE hEnd = (HANDLE)_beginthreadex(nullptr, 0, EndThread, hStart, 0 , nullptr); WaitForSingleObject(hEnd,INFINITE); return 0; }
无法正常显示
使用事件内核对象
● CreateEvent
○ CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或无名的事件对象。如果想为对象指定一个访问掩码,应当使用CreateEventEx函数。
● 函数原型
1 HANDLE WINAPI CreateEvent( 2 _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, 3 _In_ BOOL bManualReset, 4 _In_ BOOL bInitialState, 5 _In_opt_ LPCTSTR lpName 6 );
○ 参数1:lpEventAttributes[输入]
○ 一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。
○ 参数2:bManualReset[输入]
○ 指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当一个等待线程被释放以后,系统将会自动将事件状态复原为无信号状态。
○ 参数3:bInitialState[输入]
○ 指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。
○ 参数4: lpName[输入]
○ 指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。
1 #define UNICODE 2 #include <stdio.h> 3 #include <tchar.h> 4 #include <windows.h> 5 #include <process.h> 6 7 #define ___tmainCRTStartup 8 int *gPNum; 9 BOOL gUsing = FALSE; 10 11 //事件内核对象 12 //自动重置 13 //手动重置 14 void Entry() 15 { 16 while(InterlockedExchange((long*)&gUsing,TRUE) == TRUE) 17 { 18 Sleep(0); 19 } 20 } 21 void Leave() 22 { 23 InterlockedExchange((long*)&gUsing, FALSE); 24 } 25 26 void ThreadPrint(TCHAR* strText) 27 { 28 Entry(); 29 _tprintf(strText); 30 Leave(); 31 } 32 33 unsigned __stdcall StartThread(void* lParam) 34 { 35 ThreadPrint("StarThread Beging.......\r\n"); 36 gPNum = new int(0); 37 Sleep(1000); 38 ThreadPrint("StarThread End.......\r\n"); 39 return 0; 40 } 41 42 unsigned __stdcall EndThread(void* lParam) 43 { 44 ThreadPrint("EndThread Beging.......\r\n"); 45 HANDLE hStart = lParam; 46 WaitForSingleObject(hStart, INFINITE); 47 delete gPNum; 48 ThreadPrint("EndThread End.......\r\n"); 49 return 0; 50 } 51 52 int main() 53 { 54 //事件内核对象 55 HANDLE hEvent = CreateEvent(nullptr, TRUE, TRUE, TEXT("MyEvent")); 56 // TRUE 手动 57 // FALSE 自动 58 WaitForSingleObject(hEvent,INFINITE); //等待信号 Single 59 ResetEvent(hEvent); //变成NonSingle 变成没有信号的状态 60 HANDLE hStart = (HANDLE)_beginthreadex(nullptr, 0, StartThread, nullptr, 0, nullptr); 61 HANDLE hEnd = (HANDLE)_beginthreadex(nullptr, 0, EndThread, hStart, 0 , nullptr); 62 WaitForSingleObject(hEnd,INFINITE); 63 return 0; 64 }
● CreateEventEx XP 不支持 Windows Vista 支持
● 函数原型
○ 权限
○ 用户级别权限
○ 读权限或者写权限
1 HANDLE WINAPI CreateEventEx( 2 _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, 3 _In_opt_ LPCTSTR lpName, 4 _In_ DWORD dwFlags, 5 _In_ DWORD dwDesiredAccess 6 );
● lpEventAttributes[in, optional] :
○ 一个指向SECURITY_ATTRIBUTES结构的指针,如果该参数设为NULL,那么事件内核对象的句柄不能被子进程继承.
● lpName[in, optional] :
○ 指向事件内核对象的名称字符串的指针,如果该参数设为NULL,那么这个对象被创建为一个匿名事件内核对象.
● dwFlags[in] :
○ 这个参数可被设为以下一个或多个值.
○ CREATE_EVENT_INITIAL_SET 0x00000002
○ 对象初始状态为已触发,否则为未触发.
○ CREATE_EVENT_MANUAL_RESET0x00000001
○ 这个事件对象必须用ResetEvents函数手动重置,如果不设置这个标志,系统会在内核对象被释放后自动重置.
● dwDesiredAccess[in] :
○ 访问权限描述标记,详情见Synchronization Object Security and Access Rights[1]