MFC之线程(开启、挂起、恢复、终止)

MFC之线程(开启、挂起、恢复、终止)

MFC中线程有UI线程和工作者线程两种,下面分享一下MFC工作者线程的相关操作,包括线程的开启、挂起、恢复和终止。

流程:1.列举用法
2.案例展示

一:MFC线程的开启

CWinThread* AfxBeginThread(AFX_THREADPROC  pfnThreadProc,  //线程的入口函数LPVOID  pParam,   //传递入线程的参数,类型为:LPVOID,可以是结构体int nPriority = THREAD_PRIORITY_NORMAL,  //优先级,一般为 0 :和主线程具有相同的优先级.UINT nStackSize = 0,  //指定新创建的线程的栈大小。0:栈和主线程一样的大小DWORD dwCreateFlags = 0,  //默认值0:创建线程后立即运行,若是CREATE_SUSPENDED:线程创建后处于挂起状态,直到调用ResumeThread()函数。LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL  //指定新线程的安全属性,默认值NULL:新线程具有和主线程一样的安全性。);

二 :MFC线程的挂起

CwinThread::SuspendThread();

三 :MFC线程的恢复

CwinThread::ResumeThread():让挂起的线程继续执行。

主意:每个线程,系统都维持一个“计数器”,suspendThread加1,resumeThread减1,只有计数器为0时,才会给线程调度处理时间。

三 :MFC线程的终止

1. WaitForSingleObject //等待一个进程结束

  DWORD WaitForSingleObject( HANDLE hHandle,    //指明一个内核对象的句柄DWORD dwMilliseconds //等待时间(毫秒)); 该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,若该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;若该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0。第二个参数:1--INFINITE:指明要无限期等待下去,2--0:函数测试同步对象的状态并立即返回。若等待超时,该函数返回WAIT_TIMEOUT。若该函数失败,返回WAIT_FAILED。
例:
DWORD dword = WaitForSingleObject(hProcess, 5000); //等待一个进程结束
switch (dword)
{
case WAIT_OBJECT_0: // hProcess所代表的进程在5秒内结束
break;case WAIT_TIMEOUT: // 等待时间超过5秒
break;case WAIT_FAILED: // 函数调用失败,比如传递了一个无效的句柄
break;
}

2. WaitForMultipleObjects //等待多个内核对象变为已通知状态

DWORD WaitForMultipleObjects(
DWORD dwCount,           //等待内核对象的个数
CONST HANDLE* phObjects, //存放被等待的内核对象句柄的数组
BOOL bWaitAll,           //是否等到所有内核对象为已通知状态后才返回
DWORD dwMilliseconds     //等待时间
);
注意:bWaitAll参数:TRUE:只有当等待的所有内核对象为已通知状态时函数才返回:WAIT_OBJECT_0FALSE:只要一个内核对象为已通知状态该函数就返回,	成功则返回值指明是哪个内核对象收到通知。该函数失败:返回WAIT_FAILED超时:返回WAIT_TIMEOUT例:
//2个进程句柄
HANDLE hHandle[2] = {m_pthreadThreadMainCheck->m_hThread,m_pthreadEyeFor24->m_hThread};
DWORD dword = WaitForMultipleObjects(2, hHandle, FALSE, 5000); //等待3个进程结束switch (dword)
{
case WAIT_FAILED:// 函数呼叫失败
break;case WAIT_TIMEOUT:// 超时
break;case WAIT_OBJECT_0 + 0:// hHandle[0]所代表的进程结束
break;case WAIT_OBJECT_0 + 1:// hHandle[1]所代表的进程结束
break;
}

案例:

1.建立MFC对话框工程Thread,布局如下:
在这里插入图片描述
2.为3个列表框关联变量,控件类型,如下:在这里插入图片描述
3.添加9个按钮。
4.在ThreadDlg.h中创建2个线程对象,并声明2个线程函数:

class CThreadDlg : public CDialog
{
public:CThreadDlg(CWnd* pParent = NULL);	// standard constructor//XXXX//默认代码//XXXX
public:BOOL bstopAllThread;BOOL bPause;BOOL bEye24Stop;CWinThread *m_pthreadThreadMainCheck;CWinThread *m_pthreadEyeFor24;static UINT ThreadMainCheck(LPVOID lpParam);void DoThreadMainCheck();static UINT ThreadEyeFor24(LPVOID lpParam);void DoEyeFor24();CString GetInfomation(CString info);//XXXX//默认代码//XXXX

5.在CThreadDlg.cpp类中BOOL CThreadDlg::OnInitDialog()中开启线程:

BOOL CThreadDlg::OnInitDialog()
{CDialog::OnInitDialog();//XXXX//默认代码//XXXX// TODO: Add extra initialization here//初始化相关变量bstopAllThread=FALSE;bPause = FALSE;bEye24Stop = FALSE;//初始化线程变量m_pthreadThreadMainCheck = NULL;m_pthreadEyeFor24 = NULL;//开启线程:默认挂起,m_pthreadThreadMainCheck = AfxBeginThread(&ThreadMainCheck,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);m_pthreadThreadMainCheck->m_bAutoDelete = FALSE;m_pthreadThreadMainCheck->ResumeThread();m_pthreadEyeFor24 = AfxBeginThread(&ThreadEyeFor24,this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL);m_pthreadEyeFor24->m_bAutoDelete = FALSE;m_pthreadEyeFor24->ResumeThread();//XXXX//默认代码//XXXXreturn TRUE;  // return TRUE  unless you set the focus to a control
}
注意:AfxBeginThread返回的CWinThread的对象指针所指的对象在默认情况下会自动删除。当设置pThread-> m_bAutoDelete=FALSE;线程退出时是否需要delete 线程对象,默认为TRUE时线程自动delete

6.在CThreadDlg.cpp中实现线程函数

BOOL bSendMessage = FALSE;
CString infomation;
//获取信息
CString CThreadDlg:: GetInfomation(CString info)
{infomation = info;return infomation;}//主线程:监测有没有信息要输出到列表框中
UINT CThreadDlg::ThreadMainCheck(LPVOID lpParam)
{CThreadDlg *pCThreadDlg = (CThreadDlg *) lpParam;if (pCThreadDlg){pCThreadDlg->DoThreadMainCheck();}return 0;
}
//主线程内部调用的函数,具体实现
void CThreadDlg::DoThreadMainCheck()
{while(TRUE){if (bstopAllThread){break;}if (bSendMessage){SYSTEMTIME LocalSystemTime;GetLocalTime(&LocalSystemTime);CString strText;strText.Format(_T("%02d:%02d:%02d:"),LocalSystemTime.wHour,LocalSystemTime.wMinute,LocalSystemTime.wSecond);m_ListBoxWarningInfo.InsertString(0,strText + infomation);m_ListBoxWarningInfo.SetCurSel(0);while(m_ListBoxWarningInfo.GetCount() > 10){m_ListBoxWarningInfo.DeleteString(m_ListBoxWarningInfo.GetCount()-1);}}}}//电子眼线程:一直检测主线程有没有被挂起或恢复,根据具体情况更新线程状态
UINT CThreadDlg:: ThreadEyeFor24(LPVOID lpParam)
{CThreadDlg *pThreadDlg = (CThreadDlg*)lpParam;if (pThreadDlg){pThreadDlg->DoEyeFor24();}return 0;
}
void  CThreadDlg:: DoEyeFor24()
{while(TRUE){if (bEye24Stop || bstopAllThread){break;}if (bPause){	SYSTEMTIME LocalSystemTime;GetLocalTime(&LocalSystemTime);CString strText;strText.Format(_T("%02d:%02d:%02d:"),LocalSystemTime.wHour,LocalSystemTime.wMinute,LocalSystemTime.wSecond);m_Eye24.DeleteString(1);m_Eye24.InsertString(1,strText + "状态信息监测线程已暂停");m_Eye24.SetCurSel(1);Sleep(1000);}else{SYSTEMTIME LocalSystemTime;GetLocalTime(&LocalSystemTime);CString strText;strText.Format(_T("%02d:%02d:%02d:"),LocalSystemTime.wHour,LocalSystemTime.wMinute,LocalSystemTime.wSecond);m_Eye24.DeleteString(1);m_Eye24.InsertString(1,strText + "状态信息监测线程已恢复");m_Eye24.SetCurSel(1);Sleep(1000);}m_Eye24.DeleteString(0);m_Eye24.InsertString(0,"24小时电子眼监控中...");}
}

7.为每个按钮添加事件:


//雪糕类
void CThreadDlg::OnIceCream() 
{bSendMessage = TRUE;GetInfomation(_T("正被光顾:雪糕类"));bSendMessage = FALSE;CIceCream mCIceCream ;mCIceCream.DoModal();}
//冰沙类
void CThreadDlg::OnSorbet() 
{bSendMessage = TRUE;GetInfomation(_T("正被光顾:冰沙类"));bSendMessage = FALSE;CSorbet mCSorbet;mCSorbet.DoModal();}//奶茶类
void CThreadDlg::OnMilkyTea() 
{bSendMessage = TRUE;GetInfomation(_T("正被光顾:奶茶类"));bSendMessage = FALSE;CMilkyTea m_MilkyTea;m_MilkyTea.DoModal();}//暂停信息检测线程
void CThreadDlg::OnPauseMessage() 
{bPause = TRUE;m_pthreadThreadMainCheck->SuspendThread();}
//恢复信息检测线程
void CThreadDlg::OnResumeMessage() 
{bPause = FALSE;m_pthreadThreadMainCheck->ResumeThread();
}//下单按钮1:特色风味1
void CThreadDlg::OnSpecialItem1() 
{m_Order.InsertString(0,"特色风味:海南椰香奶茶 1份");m_Order.SetCurSel(0);
}
//下单按钮2:特色风味2
void CThreadDlg::OnSpecialItem2() 
{m_Order.InsertString(0,"特色风味:台式奶茶 1份");m_Order.SetCurSel(0);}
//下单按钮3:特色风味3
void CThreadDlg::OnSpecialItem3() 
{m_Order.InsertString(0,"特色风味:土耳其奶茶 1份");m_Order.SetCurSel(0);}

8.最后,线程结束是需要清理线程对象:

void CThreadDlg::OnDestroy() 
{CDialog::OnDestroy();bstopAllThread = TRUE;bPause = TRUE;bEye24Stop = TRUE;HANDLE hHandle[2] = {m_pthreadThreadMainCheck->m_hThread,m_pthreadEyeFor24->m_hThread};while (TRUE){DWORD dwObjects = WaitForMultipleObjects(2,hHandle,TRUE,0);if (dwObjects == WAIT_OBJECT_0){break;}else{MSG msg;if (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){AfxGetApp()->PumpMessage();}}}//清理线程对象delete m_pthreadThreadMainCheck;m_pthreadThreadMainCheck = NULL;delete m_pthreadEyeFor24;m_pthreadEyeFor24 = NULL;
}

这样,程序运行后,点击按钮“雪糕”,“冰沙”,“奶茶”时,左边第一个列表框中将更新显示,全程由主线程控制着,如图:
在这里插入图片描述
当按下“暂停信息”按钮时再点击上面三个按钮时,第一个列表框无法继续更新显示信息,因为“暂停信息”自行了线程挂起操作
m_pthreadThreadMainCheck->SuspendThread();
如图:
在这里插入图片描述
此时再点击“恢复信息”按钮,再按下上面“雪糕”,“沙冰”和“奶茶”按钮时,信息又可以再次更新实时信息。因为“恢复信息”按钮执行了线程的恢复操作:
m_pthreadThreadMainCheck->ResumeThread();

以上就是通过2个线程模拟奶茶店系统的过程,包含了形成的基本相关操作。
至于中间订单列表框和下单的按钮,则没有用到线程,只是通过按钮显示而已,衬托的作用。

结语:谢谢!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部