友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
喜书网 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

C语言实例教程(PDF格式)-第101章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




#include 〃afxmt。h〃。  



2。 在ThreadView。cpp 中volatile int threadController语句后加上 

下列语句:  



CEvent threadStart;  



CEvent threadEnd;  



删除语句volatile int threadController。  


…………………………………………………………Page 647……………………………………………………………

3。 用下面的代码更换ThreadProc()函数。  



UINT ThreadProc(LPVOID param)  



{  



::WaitForSingleObject(threadStart。m_hObject; INFINITE);  



::MessageBox((HWND)param; 〃Thread activated。〃; 〃Thread〃; MB_OK);  



BOOL keepRunning = TRUE;  



while (keepRunning)  



{  



int result = ::WaitForSingleObject(threadEnd。m_hObject; 0);  



if (result == WAIT_OBJECT_0)  



keepRunning = FALSE;  



}  



::PostMessage((HWND)param; WM_THREADENDED; 0; 0);  



return 0;  



}  



4。 用下面的语句替换OnStartthread()函数中的内容。  



threadStart。SetEvent();  



5。 用下面的语句替换OnStopthread()函数中的内容。  



threadEnd。SetEvent();  



6。             使用ClassWizard为CthreadView处理WM_CREATE消息的函数 

OnCreate(),并在TODO后面添加代码。OnCreate()函数如下所示:  



int CThreadView::OnCreate(LPCREATESTRUCT lpCreateStruct)   



{  



if (CView::OnCreate(lpCreateStruct) == …1)  



return …1;  



// TODO: Add your specialized creation code here  


…………………………………………………………Page 648……………………………………………………………

HWND hWnd = GetSafeHwnd();  



AfxBeginThread(ThreadProc; hWnd);  



return 0;  



}  



编译并运行这个程序,新版本的程序运行起来和旧版本的程序一样, 

但是,新版本的程序为了实现在主线程和次要线程间通信,既使用了 

CEvent类,又使用了用户定义的Windows消息。  



新版本的程序和旧版本的程序的一个大的不同在于次要线程在 

OnCreate()函数中被启动。然而由于线程函数的第一行即调用 

WaitForSingleObject(),所以此线程立即被挂起并且等待 

threadStart处于通信状态。  



当threadStart处在通信状态时,新线程显示消息框,然后进入while 

循环。这个while循环继续执行直到threadEnd处在通信状态,然后线 

程向主线程发送一个WM_THREADENDED消息并退出。因为此线程是在 

OnCreate()函数中被创建的;一旦结束,不会被重新启动。  



    



                   第三节 线程同步  



使用多线程可以带来一些非常有趣的问题。例如,如何防止两个线程 

在同一时间访问同一数据?例如,假设一个线程正在更新一个数据 

集,而同时另外一个线程正在读取数据集,结果如何?第二个线程将 

会读取到错误的数据,因为数据集中只有一部分元素被更新过。  



保持在同一个进程内的线程工作协调一致称之为线程同步。Event对 

象实际上就是线程同步的一种形式。在本节中,你将会学到三种使你 

的多线程程序更安全的线程同步对象—critical  section、互斥对象 

 (mutex)、信号量 (semaphore)。  



   (1) 使用Critical Section  



Critical  Section是一种保证在一个时间只有一个线程访问数据集的 

非常简单的方法。当你使用Critical  Section,你给了线程一个它们 

必须共享的对象。任何拥有Critical  Section对象的线程可以访问被 

保护起来的数据。其它线程必须等待直到第一个线程释放了Critical  

Section对象,此后其它线程可以按照顺序抢 占Critical   Section对 


…………………………………………………………Page 649……………………………………………………………

象,访问数据。  



因为线程只有拥有Critical  Section对象才能访问数据,而且在一个 

时刻只有一个线程可以拥有Critical  Section对象,所以决不会出现 

一个时刻有多个线程访问数据。  



为了在MFC程序中创建一个Critical                     Section对象,你应当创建 

CcriticalSection类的对象,如下所示:  



CCriticalSection criticalSection  



然后,当程序代码准备访问你保护的数据时,你应当调用 

CCriticalSection的成员函数Lock(),  



criticalSection。Lock();  



如果另外一个线程并没有拥有criticalSection,Lock()将 

criticalSection给调用它的线程。这个线程便能够访问受保护的数 

据,此后它调用CcriticalSection的成员函数Unlock() :  



criticalSection。Unlock();  



Unlock()释放了对criticalSection的拥有权,这样其它线程就可以 

占有它并访问受保护的数据。  



最好的方法是将数据放在线程安全类中。当你这样做后,你不用担心 

在主线程中的线程同步,线程安全类会替你处理的。下面的类 

CCountArray便是一个线程安全类。  



以下是COUNTARRAY。H,CcountArray的头文件。  



#include 〃afxmt。h〃  



class CCountArray  



{  



private:  



int array'10';  



CCriticalSection criticalSection;  



public:  



CCountArray() {};  


…………………………………………………………Page 650……………………………………………………………

~CCountArray() {};  



void SetArray(int value);  



void GetArray(int dstArray'10');  



};  



在该头文件中包含一个MFC的头文件afxmt。h,以使程序可以使用 

CCriticalSection类。在CCountArray类的声明中,头文件声明了一 

个十个元素的整形数组,这是CCriticalSection类的对象将要保护的 

数据,并且声明了一个CCriticalSection类的对象 

criticalSection。CCountArray类的公共成员函数包含构造和析购函 

数。后面两个成员函数用于访问数据。  



下面是CCountArray类的执行文件。注意,在每一个成员函数中, 

CCountArray都在密切关注着CCriticalSection类的对象的状态。这 

也意味这任何调用这些成员函数的线程不必担心线程同步。例如,如 

果线程1调用了SetArray();SetArray()所做的第一件事就是调用 

criticalSection。Lock();这将把criticalSection给线程1,此后可 

以完成一个循环而不用担心被其它线程打断。如果线程2调用了 

SetArray()或GetArray();criticalSection。Lock()语句将挂起线程2 

直到线程1完成循环,执行criticalSection。Unlock()语句将对 

criticalSection的拥有权释放。这时系统唤醒线程2,并将 

criticalSection给它。通过这种方式,所有线程必须安静的等待它 

们访问数据的机会到来。  



下面是COUNTARRAY。CPP,CcountArray类的执行文件。  



#include 〃stdafx。h〃  



#include 〃CountArray。h〃  



void CCountArray::SetArray(int value)  



{  



criticalSection。Lock();  



for (int x=0; x
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!