实验9多线程程序设计文档格式.docx
《实验9多线程程序设计文档格式.docx》由会员分享,可在线阅读,更多相关《实验9多线程程序设计文档格式.docx(13页珍藏版)》请在冰点文库上搜索。
//计数
BOOLgl_bclose;
//线程控制:
true-结束所有线程;
false-线程继续执行
3.2.2线程的创建:
线程靠一个CWinThread类的对象来管理,启动一个新线程的方法很
简单,用到API函数的AfxBeginThread,定义如下:
CWinThread*AFXAPIAfxBeginThread
(AFX_THREADPROCpfnThreadProc,//线程函数的地址
LPVOIDpParam,//传送到线程函数的参数
intnPriority,//(可选的)线程的优先级,默认的是
平常的优先级,
UINTnStackSize,//(可选的)线程的堆栈大小
DWORDdwCreateFlags,//(可选的)如果用户创建的线
程在开始的时候在挂起态,而不在运行态,可以设置为
CREATE_SUSPENDED
LPSECURITY_ATTRIBUTESIpSecurityAttrs
//(可选的)线程的安全属性,默认的是和父线程的访问权限一样
);
函数AfxBeginThread启动新线程并返回一个线程对象指针,然后,
新线程和启动新线程的线程同时运行。
函数的第一个参数指定线程函数。
新线程首先执行这个函数,在这个函数中可以再调用其他函数完成新线程的工作,这个
函数执行完毕返回时,新线程结束。
线程函数不能是任意定义,必须定义如下:
UINTThreadFunction(LPVOIDpParam);
这个函数必须被定义成全局函数,函数的返回类型必须是UINT,必须有一
个LPVOID类型的参数,这个参数一般使用AfxBeginThread函数的第二
个参数pParam。
函数的返回值在函数中任意定义(但不能返回特殊值STILL_AVTIVE,它被定义成0X00000I03L,表示线程仍在运行,引起混淆)。
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」=0;
};
voidSet(inti){m」=i;
voidSetId(inti){id=i;
};
intGet(){returnm」;
intGetId(){returnid;
voidInc(){m」+=1;
private:
intm_i;
//累计值
intid;
//线程编号};
UINTtestThread1(LPV0IDpParam){//线程主函数
//接收一个窗口类指针,然后设置窗口标题
HWNDhWnd=(HWND)pParam;
//将传入的线程函数参数转换
为窗口句柄
while(!
gl_bclose){//判别gl_bclose是否为TRUE,否则线程继续运行Sleep(IOOO);
//1s
gl_i+=100;
//延时累加
}_
charstr[81];
wsprintf(str,"
全局变量值:
%d"
gl_i);
AfxMessageBox(str);
//显示gl」值
return0;
//返回并退出线程
//或者调用voidAfxEndThread(UINTnExitCode);
来退出
}
voidOnThreadCreate()
gl_bclose=FALSE;
HWNDhWnd=GetSafeHwnd();
AfxBeginThread(testThread1,hWnd);
//创建工作线程
3.3第二部分一创建优先级不同的双线程:
331创建双线程:
虽然是创建双线程,但其实两个线程的内部工作方式相同,只是传递的参数
不同,因此只需一个线程函数即可:
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();
wsprintf(str,"
线程%d累计值:
pCtest9->
Getld(),pCtest9->
Get());
AfxMessageBox(str);
if(pCtest9!
=NULL){deletepCtest9;
}voidCMainFrame:
:
OnDoublethreadCreate()
Ctest9*pCtest9_1;
pCtest9_1=newCtest9;
pCtest9_1->
Setld
(1);
LPVOIDpParam1=(LPVOID)pCtest9_1;
AfxBeginThread(testDoubleThread,pParam1,THREAD_PRIORITY_ABOVE_NORMAL);
Ctest9*pCtest9_2;
pCtest9_2=newCtest9;
pCtest9_2->
Setld
(2);
LPVOIDpParam2=(LPVOID)pCtest9_2;
AfxBeginThread(testDoubleThread,pParam2,THREAD_PRIORITY_BELOW_NORMAL);
3.4第三部分一线程的控制:
3.4.1为工程添加变量:
为3个EditBox分别添加成员变量:
intm_Value1;
//计数初始值
intm_Value2;
//计数增量
intm_Value3;
//计数结果
四个按钮分别用来创建线程,暂停/运行,终止线程,显示最终结果。
按钮的状态可由下面两个函数控制:
CButton:
EnableWindow(BOOLbEnable);
//TRUE——可用;
FALSE——不可用(变灰)
SetWindowText(LPCTSTRpszString);
//实现将按钮上的字符改变
添加全局变量:
//线程结束标志
//线程挂起标志
boolpause_flag=FALSE;
boolend_flag=FALSE;
intgl_last=0;
//全局变量,存放累加值
最终结果如下图:
图1:
创建线程
图2:
线程挂起
图3:
线程结束并显示结果第三部分程序如下:
//线程结束标志
//线程挂起标志
classCTest9_3
CTest9_3(){m」nitValue=m_Step=0;
voidlnc(){m」nitValue+=m_Step;
intGetValue(){returnm」nitValue;
voidSetValue(intv1,intv2){m」nitValue=v1;
m_Step=v2;
}protected:
private:
intm」nitValue;
intm_Step;
//〉程序与线程传递的参数
UINTtestThread3(LPVOIDpParam){
CTest9_3*lpc=(CTest9_3*)pParam;
end_flag)//线程是否结束?
Sleep(50);
//线程休眠}
Sleep(1000);
lpc->
Inc();
//延时累加,1s
gl_last=lpc->
GetValue();
//线程结束,保存累加值
if(lpc!
=NULL){deletelpc;
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
挂起"
//线程挂起时显示“运行”}
voidOnThreadEnd()
EnableWindow(TRUE);
//使“启动”按钮恢复作用
voidOnValueMove()
//TODO:
Addyourcontrolnotificationhandlercodehere
m_LastValue=gl_last;
UpdateData(FALSE);
//将累加值传递给EditBox变量并在EditBox中显示