实验9 多线程程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验九多线程程序设计
一、实验目的
1、工作线程的创建;
2、多线程的创建;
3、主程序与线程间数据交换;
4、线程工作状态设置及修改。
二、实验要求
2.1 创建一个窗口,建立子菜单(创建线程(BEGIN_THREAD)、线程关闭(CLOSE)),利用创建线程BEGIN_THREAD,创建许多工作线程,利用线程关闭(CLOSE)所有线程。每个工作线程都对全局变量int gl_i加100,然后在线程中判别全局变量BOOL gl_bclose,当判别为线程结束时,将当前线程获得的gl_i在对话中显示(即中间对话中显示的值)。
注意,由于线程是一个简单的延时后累加的过程,所有随着控制线程是否结束的时间不同,得到的值是不相同的。
控制线程结束,利用线程关闭(CLOSE)实现对gl_bclose的修改。
2.2 同1,要求利用子菜单选择同时启动两个线程,在这两个线程中分别有各自的累加值并在线程中对其进行累加,不过要求两个线程有不同的优先级别,当线程关闭后,显示两线程当前的累计值。
2.3 编写一个线程,功能是将主程序通过利用参数传递方法传递给线程的一个整型数(或一个类)定时累加。建立一个对话窗口,有线程的‘启动’、‘挂起’/‘运行’和‘停止’三个按钮,‘启动按钮’实现启动一个线程,‘挂起’/‘运行’是一个按钮,是根据当前线程的状态设置,显然当线程在‘运行’状况,该按钮应该显示‘挂起’,反之,显示‘运行’,当按该按钮后,使线程处于挂起状态或运行状态,‘停止’按钮显然是停止该线程的运行。另有一个‘MOVE’按钮和一个编辑控件,按‘MOVE’按钮将当前线程中的整型值在编辑控件上显示。
目的:了解线程与主程序间的参数传递。
三、实验过程
3.1首先创建单文档工程,如下图:
3.2 第一部分──线程的创建与结束:
3.2.1添加全局变量:
int gl_i; //计数
BOOL gl_bclose;
//线程控制:true-结束所有线程;false-线程继续执行
3.2.2线程的创建:
线程靠一个CWinThread类的对象来管理,启动一个新线程的方法很简单,用到API函数的AfxBeginThread,定义如下:
CWinThread * AFXAPI AfxBeginThread
(AFX_THREADPROC pfnThreadProc, // 线程函数的地址
LPVOID pParam,//传送到线程函数的参数
int nPriority,// (可选的)线程的优先级,默认的是平常的优先级,
UINT nStackSize,// (可选的)线程的堆栈大小
DWORD dwCreateFlags, // (可选的)如果用户创建的线程在开始的时候在挂起态,而不在运行态,可以设置为
CREATE_SUSPENDED
LPSECURITY_ATTRIBUTES lpSecurityAttrs
// (可选的)线程的安全属性,默认的是和父线程的访问权限一样
);
函数AfxBeginThread 启动新线程并返回一个线程对象指针,然后,新线程和启动新线程的线程同时运行。函数的第一个参数指定线程函数。新线程首先执行这个函数,在这个函数中可以再调用其他函数完成新线程的工作,这个函数执行完毕返回时,新线程结束。线程函数不能是任意定义,必须定义如下:UINT ThreadFunction(LPVOID pParam);
这个函数必须被定义成全局函数,函数的返回类型必须是UINT,必须有一个LPVOID类型的参数,这个参数一般使用AfxBeginThread 函数的第二个参数pParam。函数的返回值在函数中任意定义(但不能返回特殊值
STILL_AVTIVE,它被定义成0X00000l03L,表示线程仍在运行,引起混淆)。
AfxBeginThread函数的具体用法可查阅MSDN。
3.2.3线程函数:
线程函数定义了线程要做什么,在进入这个函数的时候线程开始,退出的时候线程结束。这个函数称为线程函数,定义如下:
UINT ThreadFunction( LPVOID pParam );
这里:ThreadFunction 是线程函数名,就是启动线程函数的第一个参数pfnThreadProc。
参数LPVOID pParam 是启动线程函数的第二个参数,该参数是一个32位数,是在线程对象创建时传送给对象的构造函数。线程函数根据需要进行对参数进行处理,实际上,线程和主程序之间可以利用这个参数实现数据传递。
3.2.4终止线程:
线程终止由两种方法,一种是等待线程函数执行完毕后自动退出,线程退出后创建的线程对象是否自动删除,是由CWinThread 对象的一个成员变量
m_bAutoDelete决定,为TRUE时,线程执行后自动删除创建的CWinThread 对象,否则,在线程结束后,该对象并不删除,需要外部来删除。
可以在线程创建后对m_bAutoDelete 设置。
如:m_pDrawThread -> m_bAutoDelete = FALSE ;
这样,在线程执行结束后并不删除,需要外部去删除:
delete m_pDrawThread;
另一个终止线程的方法是调用MFC函数AfxEndThread:
void AFXAPI AfxEndThread( UINT nExitCode, BOOL bDelete );
延时计数可利用函数:
VOID Sleep(
DWORD dwMilliseconds// 延时长度(单位:毫秒)
);
实验九第一部分最终结果如下图:
第一部分程序如下:
class Ctest9 // 定义一个类
{
public:
Ctest9(){ m_i = 0 ;};
void Set( int i ) { m_i = i ;};
void SetId( int i ) { id = i; };
int Get() { return m_i ;} ;
int GetId() { return id ;} ;
void Inc() { m_i += 1 ;};
private:
int m_i; //累计值
int id; //线程编号} ;