八、线程的同步(二)

本篇介绍使用事件。  

事件是一种可用于同步的对象。一个事件对象可以有两种状态:有信号状态和无信号状态。  

在MFC中,通过CEvent 类实现对事件的支持。一个CEvent对象在刚建立时可以设置有信号或无信号状态。默认是无信号状态。

CEvent对象有两种类型:人工事件和自动事件。在创建CEvent 类的对象时,默认创建的是自动事件。

一个自动CEvent 对象在被至少一个线程释放后会自动返回到无信号状态;

而人工事件对象获得信号后,释放可利用线程,但直到调用成员函数ResetEvent()才将其设置为无信号状态。

CEvent 类的各成员函数的原型和参数说明如下:

1. CEvent( BOOL bInitiallyOwn=FALSE,
           BOOL bManualReset=FALSE,
           LPCTSTR lpszName=NULL,
           LPSECURITY_ATTRIBUTES lpsaAttribute=NULL); 

bInitiallyOwn:指定事件对象初始化状态,TRUE为有信号,FALSE为无信号; 

bManualReset:指定要创建的事件是属于人工事件还是自动事件。TRUE为人工事件,FALSE为自动事件; 

后两个参数一般设为NULL,在此不作过多说明。

2. BOOL CEvent::SetEvent();

将 CEvent 类对象的状态设置为有信号状态。如果事件是人工事件,则 CEvent 类对象保持为有信号状态,直到调用成员函数ResetEvent()将其重新设为无信号状态时为止。

如果CEvent 类对象为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent 类对象由系统自动重置为无信号状态。

3. BOOL CEvent::ResetEvent()

该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数。

一般通过调用WaitForSingleObject函数来监视事件状态。

下面开始写程序:

1. 建立一个基于对话框的工程MultiThread9,在对话框IDD_MULTITHREAD9_DIALOG中加入一个按钮和两个编辑框控件,按钮的ID为IDC_WRITEW,标题为“写‘W’”;两个编辑框的ID分别为IDC_W和IDC_D,属性都选中Read-only;注意把编辑框拉长一点,以容得下10个字母。

2. 使用ClassWizard分别给IDC_W和IDC_D添加CEdit类变量m_ctrlW和m_ctrlD;

3. 在MultiThread9Dlg.h文件中声明两个线程函数:

UINT WriteW(LPVOID pParam);   
UINT WriteD(LPVOID pParam);  

4. 在MultiThread9Dlg.cpp文件中添加如下内容:

    为了文件中能够正确使用同步类,在文件开头添加:

#include "afxmt.h"

    定义临界区和一个字符数组,为了能够在不同线程间使用,定义为全局变量:

CEvent eventWriteD; 
char g_Array[10];

    添加线程函数:

UINT WriteW(LPVOID pParam)
{
	CEdit *pEdit = (CEdit*)pParam;
	pEdit->SetWindowText(""); //先清空编辑框
	
	for (int i=0; i<10; ++i)
	{
		g_Array[i] = 'W';
		pEdit->SetWindowText(g_Array);
		Sleep(1000);
	}
	eventWriteD.SetEvent();
	return 0;
}

UINT WriteD(LPVOID pParam)
{
	CEdit *pEdit = (CEdit*)pParam;
	pEdit->SetWindowText(""); //先清空编辑框
 	
	WaitForSingleObject(eventWriteD.m_hObject, INFINITE);
	for (int i=0; i<10; ++i)            
	{
		g_Array[i] = 'D';
		pEdit->SetWindowText(g_Array);
		Sleep(1000);
	}
	return 0;
}

5. 双击按钮IDC_WRITEW,添加其响应函数: 

void CMultiThread9Dlg::OnWritew() 
{
	// TODO: Add your control notification handler code here
	CWinThread *pWriteW=AfxBeginThread(WriteW, &m_ctrlW);//, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);  
	//pWriteW->ResumeThread();  
	CWinThread *pWriteD=AfxBeginThread(WriteD, &m_ctrlD);//, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	//pWriteD->ResumeThread();
}

6. 编译、运行。

分析:

事件enventWriteD对象开始是无信号。单击按钮后建立两个线程WriteW和WriteD。

线程WriteD执行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);处等待,直到事件eventWriteD为有信号该线程才往下执行。

线程WriteW在返回之前通过调用SetEvent将事件设置为有信号。WriteD函数就可以继续执行。

这个程序跟上一个很接近。因此同样可以在运行时查看任务管理器。 

对于Windows事件的理解,可以参考以下MSDN的网页:

http://msdn.microsoft.com/library/windows/desktop/ms682655

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686915

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值