实验9 多线程程序设计.docx

上传人:b****5 文档编号:3402642 上传时间:2022-11-22 格式:DOCX 页数:12 大小:112.26KB
下载 相关 举报
实验9 多线程程序设计.docx_第1页
第1页 / 共12页
实验9 多线程程序设计.docx_第2页
第2页 / 共12页
实验9 多线程程序设计.docx_第3页
第3页 / 共12页
实验9 多线程程序设计.docx_第4页
第4页 / 共12页
实验9 多线程程序设计.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

实验9 多线程程序设计.docx

《实验9 多线程程序设计.docx》由会员分享,可在线阅读,更多相关《实验9 多线程程序设计.docx(12页珍藏版)》请在冰豆网上搜索。

实验9 多线程程序设计.docx

实验9多线程程序设计

实验九多线程程序设计

一、实验目的

1、工作线程的创建;

2、多线程的创建;

3、主程序与线程间数据交换;

4、线程工作状态设置及修改。

二、实验要求

2.1创建一个窗口,建立子菜单(创建线程(BEGIN_THREAD)、线程关闭(CLOSE)),利用创建线程BEGIN_THREAD,创建许多工作线程,利用线程关闭(CLOSE)所有线程。

每个工作线程都对全局变量intgl_i加100,然后在线程中判别全局变量BOOLgl_bclose,当判别为线程结束时,将当前线程获得的gl_i在对话中显示(即中间对话中显示的值)。

注意,由于线程是一个简单的延时后累加的过程,所有随着控制线程是否结束的时间不同,得到的值是不相同的。

控制线程结束,利用线程关闭(CLOSE)实现对gl_bclose的修改。

2.2同1,要求利用子菜单选择同时启动两个线程,在这两个线程中分别有各自的累加值并在线程中对其进行累加,不过要求两个线程有不同的优先级别,当线程关闭后,显示两线程当前的累计值。

2.3编写一个线程,功能是将主程序通过利用参数传递方法传递给线程的一个整型数(或一个类)定时累加。

建立一个对话窗口,有线程的‘启动’、‘挂起’/‘运行’和‘停止’三个按钮,‘启动按钮’实现启动一个线程,‘挂起’/‘运行’是一个按钮,是根据当前线程的状态设置,显然当线程在‘运行’状况,该按钮应该显示‘挂起’,反之,显示‘运行’,当按该按钮后,使线程处于挂起状态或运行状态,‘停止’按钮显然是停止该线程的运行。

另有一个‘MOVE’按钮和一个编辑控件,按‘MOVE’按钮将当前线程中的整型值在编辑控件上显示。

目的:

了解线程与主程序间的参数传递。

三、实验过程

3.1首先创建单文档工程,如下图:

3.2第一部分──线程的创建与结束:

3.2.1添加全局变量:

intgl_i;//计数

BOOLgl_bclose;

//线程控制:

true-结束所有线程;false-线程继续执行

3.2.2线程的创建:

线程靠一个CWinThread类的对象来管理,启动一个新线程的方法很简单,用到API函数的AfxBeginThread,定义如下:

CWinThread*AFXAPIAfxBeginThread

(AFX_THREADPROCpfnThreadProc,//线程函数的地址

LPVOIDpParam,              //传送到线程函数的参数

intnPriority,   // (可选的)线程的优先级,默认的是平常的优先级,

UINTnStackSize,    // (可选的)线程的堆栈大小

DWORDdwCreateFlags,// (可选的)如果用户创建的线程在开始的时候在挂起态,而不在运行态,可以设置为CREATE_SUSPENDED

LPSECURITY_ATTRIBUTESlpSecurityAttrs

//(可选的)线程的安全属性,默认的是和父线程的访问权限一样

);

   函数AfxBeginThread启动新线程并返回一个线程对象指针,然后,新线程和启动新线程的线程同时运行。

函数的第一个参数指定线程函数。

新线程首先执行这个函数,在这个函数中可以再调用其他函数完成新线程的工作,这个函数执行完毕返回时,新线程结束。

线程函数不能是任意定义,必须定义如下:

   UINTThreadFunction(LPVOIDpParam);

   这个函数必须被定义成全局函数,函数的返回类型必须是UINT,必须有一个LPVOID类型的参数,这个参数一般使用AfxBeginThread函数的第二个参数pParam。

函数的返回值在函数中任意定义(但不能返回特殊值STILL_AVTIVE,它被定义成0X00000l03L,表示线程仍在运行,引起混淆)。

AfxBeginThread函数的具体用法可查阅MSDN。

3.2.3线程函数:

线程函数定义了线程要做什么,在进入这个函数的时候线程开始,退出的时候线程结束。

这个函数称为线程函数,定义如下:

 UINTThreadFunction(LPVOIDpParam);

这里:

ThreadFunction是线程函数名,就是启动线程函数的第一个参数pfnThreadProc。

参数LPVOIDpParam是启动线程函数的第二个参数,该参数是一个32位数,是在线程对象创建时传送给对象的构造函数。

线程函数根据需要进行对参数进行处理,实际上,线程和主程序之间可以利用这个参数实现数据传递。

3.2.4终止线程:

线程终止由两种方法,一种是等待线程函数执行完毕后自动退出,线程退出后创建的线程对象是否自动删除,是由CWinThread对象的一个成员变量m_bAutoDelete决定,为TRUE时,线程执行后自动删除创建的CWinThread对象,否则,在线程结束后,该对象并不删除,需要外部来删除。

可以在线程创建后对m_bAutoDelete设置。

如:

m_pDrawThread->m_bAutoDelete=FALSE; 

这样,在线程执行结束后并不删除,需要外部去删除:

  deletem_pDrawThread; 

另一个终止线程的方法是调用MFC函数AfxEndThread:

 voidAFXAPIAfxEndThread(UINTnExitCode,BOOLbDelete);

延时计数可利用函数:

VOIDSleep(

DWORDdwMilliseconds//延时长度(单位:

毫秒)

);

实验九第一部分最终结果如下图:

第一部分程序如下:

classCtest9//定义一个类

{

public:

Ctest9(){m_i=0;};

voidSet(inti){m_i=i;};

voidSetId(inti){id=i;};

intGet(){returnm_i;};

intGetId(){returnid;};

voidInc(){m_i+=1;};

private:

intm_i;//累计值

intid;//线程编号};

UINTtestThread1(LPVOIDpParam){//线程主函数

//接收一个窗口类指针,然后设置窗口标题

HWNDhWnd=(HWND)pParam;//将传入的线程函数参数转换为窗口句柄

while(!

gl_bclose){//判别gl_bclose是否为TRUE,否则线程继续运行

Sleep(1000);//1s

gl_i+=100;//延时累加

}

charstr[81];

wsprintf(str,"全局变量值:

%d",gl_i);

AfxMessageBox(str);//显示gl_i值

return0;//返回并退出线程

//或者调用voidAfxEndThread(UINTnExitCode);来退出

}

voidOnThreadCreate()

{

gl_bclose=FALSE;

HWNDhWnd=GetSafeHwnd();

AfxBeginThread(testThread1,hWnd);//创建工作线程

}

3.3第二部分──创建优先级不同的双线程:

3.3.1创建双线程:

虽然是创建双线程,但其实两个线程的内部工作方式相同,只是传递的参数不同,因此只需一个线程函数即可:

UINTtestDoubleThread(LPVOIDpParam);

然后利用3.2.2中提到的AfxBeginThread()来创建线程:

AfxBeginThread(testDoubleThread,pParam1,THREAD_PRIORITY_ABOVE_NORMAL);

//创建第一个线程,优先级高于默认

AfxBeginThread(testDoubleThread,pParam2,THREAD_PRIORITY_BELOW_NORMAL);

//创建第二个线程,优先级低于默认

3.3.2终止双线程:

同样可以利用3.2中的全局变量gl_bclose来控制线程的结束。

最终结果如下图:

第二部分程序如下:

UINTtestDoubleThread(LPVOIDpParam){//线程主函数

Ctest9*pCtest9;

pCtest9=(Ctest9*)pParam;

while(!

gl_bclose)

{

Sleep(500);

pCtest9->Inc();

}

charstr[81];

wsprintf(str,"线程%d累计值:

%d",pCtest9->GetId(),pCtest9->Get());

AfxMessageBox(str);

if(pCtest9!

=NULL){deletepCtest9;}

return0;

}

voidCMainFrame:

:

OnDoublethreadCreate()

{

gl_bclose=FALSE;

Ctest9*pCtest9_1;

pCtest9_1=newCtest9;

pCtest9_1->SetId

(1);

LPVOIDpParam1=(LPVOID)pCtest9_1;

AfxBeginThread(testDoubleThread,pParam1,THREAD_PRIORITY_ABOVE_NORMAL);

//创建第一个线程,优先级高于默认

Ctest9*pCtest9_2;

pCtest9_2=newCtest9;

pCtest9_2->SetId

(2);

LPVOIDpParam2=(LPVOID)pCtest9_2;

AfxBeginThread(testDoubleThread,pParam2,THREAD_PRIORITY_BELOW_NORMAL);

//创建第二个线程,优先级低于默认

}

3.4第三部分──线程的控制:

3.4.1插入对话框,如下图:

3.4.1为工程添加变量:

为3个EditBox分别添加成员变量:

intm_Value1;//计数初始值

intm_Value2;//计数增量

intm_Value3;//计数结果

四个按钮分别用来创建线程,暂停/运行,终止线程,显示最终结果。

按钮的状态可由下面两个函数控制:

CButton:

:

EnableWindow(BOOLbEnable);

//TRUE——可用;FALSE——不可用(变灰)

CButton:

:

SetWindowText(LPCTSTRpszString);

//实现将按钮上的字符改变

添加全局变量:

boolpause_flag=FALSE;//线程结束标志

boolend_flag=FALSE;//线程挂起标志

intgl_last=0;//全局变量,存放累加值

最终结果如下图:

图1:

创建线程

图2:

线程挂起

图3:

线程结束并显示结果

第三部分程序如下:

boolpause_flag=FALSE;//线程结束标志

boolend_flag=FALSE;//线程挂起标志

intgl_last=0;//全局变量,存放累加值

classCTest9_3

{

public:

CTest9_3(){m_InitValue=m_Step=0;}

voidInc(){m_InitValue+=m_Step;}

intGetValue(){returnm_InitValue;}

voidSetValue(intv1,intv2){m_InitValue=v1;m_Step=v2;}

protected:

private:

intm_InitValue;

intm_Step;

};//主程序与线程传递的参数

UINTtestThread3(LPVOIDpParam){

CTest9_3*lpc=(CTest9_3*)pParam;

while(!

end_flag)//线程是否结束?

{

while(pause_flag)//线程是否挂起?

{

Sleep(50);//线程休眠

}

Sleep(1000);

lpc->Inc();//延时累加,1s

}

gl_last=lpc->GetValue();//线程结束,保存累加值

if(lpc!

=NULL){deletelpc;}

return0;

}

voidOnThreadBegin()

{

end_flag=FALSE;

pause_flag=FALSE;

gl_last=0;//初始化

UpdateData(TRUE);//获取输入的初始值以及步长值

CTest9_3*lpc;

lpc=newCTest9_3;

lpc->SetValue(m_InitValue,m_Step);

LPVOIDpParam=(LPVOID)lpc;//定义线程操作的数据

CButton*button=(CButton*)GetDlgItem(IDC_THREAD_BEGIN);

button->EnableWindow(FALSE);//“启动”按钮失效(变灰)

AfxBeginThread(testThread3,pParam);//启动线程

}

voidOnThreadRunpause()

{

CButton*button=(CButton*)GetDlgItem(IDC_THREAD_RUNPAUSE);

if(!

pause_flag)

{

pause_flag=TRUE;

button->SetWindowText("运行");//线程运行时显示“挂起”

}

else

{

pause_flag=FALSE;

button->SetWindowText("挂起");//线程挂起时显示“运行”

}

}

voidOnThreadEnd()

{

end_flag=TRUE;//通知线程结束

CButton*button=(CButton*)GetDlgItem(IDC_THREAD_BEGIN);

button->EnableWindow(TRUE);//使“启动”按钮恢复作用

}

voidOnValueMove()

{

//TODO:

Addyourcontrolnotificationhandlercodehere

m_LastValue=gl_last;

UpdateData(FALSE);//将累加值传递给EditBox变量并在EditBox中显示

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1