关于事件

  事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
  (1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
  (2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。
  创建事件的函数原型为:

HANDLE CreateEvent(
 LPSECURITY_ATTRIBUTES lpEventAttributes,
 // SECURITY_ATTRIBUTES结构指针,可为NULL
 BOOL bManualReset,
 // 手动/自动
 // TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号
 // FALSE:在WaitForSingleObject后,系统自动清除事件信号
 BOOL bInitialState, //初始状态
 LPCTSTR lpName //事件的名称
);

使用"事件"机制应注意以下事项:
  (1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
  (2)事件是否要自动恢复;
  (3)事件的初始状态设置。


看下面代码:

  1. DWORD WINAPI ThreadProc(LPVOID lpParam);
  2. DWORD WINAPI ThreadProc2(LPVOID lpParam);
  3. DWORD g_dwThreadID;
  4. DWORD g_dwThreadID2;
  5. UINT g_nTickets = 300;//int g_nTickets = 300; //备注1
  6. HANDLE g_hEvent = NULL;
  7. HANDLE g_hEvent1 = NULL;
  8. HANDLE g_hEvent2 = NULL;
  9. CRITICAL_SECTION g_cs;
  10. int ThreadCout = 0;
  11. int main()
  12. {
  13. cout << "Main thread is running." << endl;
  14. InitializeCriticalSection(&g_cs);//初始化临界区
  15. HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID);
  16. ThreadCout++;
  17. HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2);
  18. ThreadCout++;
  19. //g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
  20. g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent1 = CreateEvent(NULL, TRUE, TRUE, NULL);
  21. g_hEvent2 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent2 = CreateEvent(NULL, TRUE, TRUE, NULL);
  22. ResetEvent(g_hEvent1);
  23. ResetEvent(g_hEvent2);
  24. SetEvent(g_hEvent1);
  25. while (TRUE)
  26. {
  27. EnterCriticalSection(&g_cs);
  28. int nCount = ThreadCout;
  29. LeaveCriticalSection(&g_cs);
  30. if (nCount == 0)
  31. {
  32. cout << "Main thread is break." << endl;
  33. break;
  34. }
  35. }
  36. Sleep(1000); //备注4
  37. CloseHandle(hHandle);
  38. CloseHandle(hHandle2);
  39. DeleteCriticalSection(&g_cs);
  40. cout << "Main thread is end." << endl;
  41. system("pause");
  42. return 0;
  43. }
  44. DWORD WINAPI ThreadProc(LPVOID lpParam)
  45. {
  46. // cout << "No." << g_dwThreadID << " thread is running." << endl;
  47. while (TRUE)
  48. {
  49. WaitForSingleObject(g_hEvent1, INFINITE);
  50. cout << "No.1 " << g_dwThreadID <<" thread is running." << endl;
  51. EnterCriticalSection(&g_cs);
  52. int temp= g_nTickets;
  53. LeaveCriticalSection(&g_cs);
  54. cout << "No.1 " << g_dwThreadID <<" thread is temp." << endl;
  55. if (temp > 0)
  56. {
  57. Sleep(10); //Sleep(1000) //备注2
  58. cout << "No.1-" << g_dwThreadID <<" sell ticket : " << temp << endl;
  59. EnterCriticalSection(&g_cs);
  60. g_nTickets--;
  61. LeaveCriticalSection(&g_cs);
  62. SetEvent(g_hEvent2);
  63. //ResetEvent(g_hEvent1);//备注6
  64. }
  65. else
  66. {
  67. cout << "No.1- break" << endl;
  68. //ResetEvent(g_hEvent1);//备注6
  69. SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止 //备注3
  70. break;
  71. }
  72. }
  73. EnterCriticalSection(&g_cs);
  74. ThreadCout--;
  75. LeaveCriticalSection(&g_cs);
  76. cout << "No.1- end" << endl;
  77. return 0;
  78. }
  79. DWORD WINAPI ThreadProc2(LPVOID lpParam)
  80. {
  81. //
  82. while (TRUE)
  83. {
  84. WaitForSingleObject(g_hEvent2, INFINITE);
  85. cout << "No.2 " << g_dwThreadID2 <<" thread is running." << endl;
  86. EnterCriticalSection(&g_cs);
  87. int temp= g_nTickets;
  88. LeaveCriticalSection(&g_cs);
  89. if (temp > 0)
  90. {
  91. Sleep(10); //Sleep(1000) //备注2
  92. cout << "No.2-" << g_dwThreadID2 <<" sell ticket : " << temp << endl;
  93. EnterCriticalSection(&g_cs);
  94. g_nTickets--;
  95. LeaveCriticalSection(&g_cs);
  96. SetEvent(g_hEvent1);
  97. //ResetEvent(g_hEvent2);//备注6
  98. }
  99. else
  100. {
  101. cout << "No.2- break" << endl;
  102. //ResetEvent(g_hEvent2);//备注6
  103. SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止 //备注3
  104. break;
  105. }
  106. }
  107. EnterCriticalSection(&g_cs);
  108. ThreadCout--;
  109. LeaveCriticalSection(&g_cs);
  110. cout << "No.2- end" << endl;
  111. return 0;
  112. }
DWORD WINAPI ThreadProc(LPVOID lpParam);  
DWORD WINAPI ThreadProc2(LPVOID lpParam);  

DWORD g_dwThreadID;  
DWORD g_dwThreadID2;  

UINT g_nTickets = 300;  //int g_nTickets = 300;  //备注1
HANDLE g_hEvent = NULL;  

HANDLE g_hEvent1 = NULL; 
HANDLE g_hEvent2 = NULL; 

CRITICAL_SECTION g_cs;

int ThreadCout = 0;

int main()  
{  
	cout << "Main thread is running." << endl;  

	InitializeCriticalSection(&g_cs);//初始化临界区
	
	HANDLE hHandle = CreateThread(NULL, 0, ThreadProc, NULL, 0, &g_dwThreadID);  
	ThreadCout++;
	HANDLE hHandle2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, &g_dwThreadID2); 
	ThreadCout++;

	//g_hEvent = CreateEvent(NULL, FALSE,  TRUE, NULL);  
	g_hEvent1 = CreateEvent(NULL, FALSE,  TRUE, NULL);  //备注5:g_hEvent1 = CreateEvent(NULL, TRUE,  TRUE, NULL);
	g_hEvent2 = CreateEvent(NULL, FALSE,  TRUE, NULL);	//备注5:g_hEvent2 = CreateEvent(NULL, TRUE,  TRUE, NULL);

	ResetEvent(g_hEvent1);
	ResetEvent(g_hEvent2);

	SetEvent(g_hEvent1); 


	while (TRUE)
	{
		EnterCriticalSection(&g_cs);
		int nCount = ThreadCout;  
		LeaveCriticalSection(&g_cs);

		if (nCount == 0)
		{
			cout << "Main thread is break." << endl; 
			break;
		}

	}

	
	Sleep(1000);	//备注4	
	
	CloseHandle(hHandle);   
	CloseHandle(hHandle2);  

	DeleteCriticalSection(&g_cs);

	cout << "Main thread is end." << endl;

	system("pause");  
	return 0;  
}  

DWORD WINAPI ThreadProc(LPVOID lpParam)  
{   
	// cout << "No." << g_dwThreadID << " thread is running." << endl;  
	while (TRUE)  
	{  
		WaitForSingleObject(g_hEvent1, INFINITE);  
		cout << "No.1 " << g_dwThreadID << " thread is running." << endl;  

		EnterCriticalSection(&g_cs);
		int temp= g_nTickets; 
		LeaveCriticalSection(&g_cs);

		cout << "No.1 " << g_dwThreadID << " thread is temp." << endl; 

		if (temp > 0)  
		{  
			Sleep(10);  //Sleep(1000)	//备注2
			cout << "No.1-" << g_dwThreadID << " sell ticket : " << temp << endl; 
			
			
			EnterCriticalSection(&g_cs);
			g_nTickets--;  
			LeaveCriticalSection(&g_cs);

			SetEvent(g_hEvent2); 
			//ResetEvent(g_hEvent1);//备注6
			  

		}  
		else  
		{  
			cout << "No.1- break" << endl;
			//ResetEvent(g_hEvent1);//备注6
			SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止	//备注3
			break;  
		}  
	}  

	EnterCriticalSection(&g_cs);
	ThreadCout--;  
	LeaveCriticalSection(&g_cs);
	cout << "No.1- end" << endl;

	return 0;  
}  

DWORD WINAPI ThreadProc2(LPVOID lpParam)  
{  
	// 
	while (TRUE)  
	{  
		WaitForSingleObject(g_hEvent2, INFINITE);  
		cout << "No.2 " << g_dwThreadID2 << " thread is running." << endl;  

		EnterCriticalSection(&g_cs);
		int temp= g_nTickets; 
		LeaveCriticalSection(&g_cs);

		if (temp > 0)  
		{  
			Sleep(10);  //Sleep(1000)	//备注2
			cout << "No.2-" << g_dwThreadID2 << " sell ticket : " << temp << endl;  

			EnterCriticalSection(&g_cs);
			g_nTickets--;  
			LeaveCriticalSection(&g_cs);

			SetEvent(g_hEvent1); 
			//ResetEvent(g_hEvent2);//备注6
		}  
		else  
		{  
			cout << "No.2- break" << endl;
			//ResetEvent(g_hEvent2);//备注6
			SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止		//备注3
			break;  
		}  
	}  

	EnterCriticalSection(&g_cs);
	ThreadCout--;  
	LeaveCriticalSection(&g_cs);

	cout << "No.2- end" << endl;
	return 0;  
}  


这个代码是接上一遍关于UINT类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。
本文要说明的是SetEvent和ResetEvent的使用,这个要看备注5和备注6。
备注5处:
CreateEvent的第二个参数决定了是否需要手动调用ResetEvent,当为TRUE时,是需要手动调用,如果不调用,会怎么样呢?不调用,事件会处于一直有信号状态,即备注6处。当为FALSE时候,不需要手动调用,调用不调用,效果一样。把ResetEvent放在 WaitForSingleObject前面也是很好的做法
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值