————————————————
版权声明:本文为CSDN博主「三公子Tjq」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/naibozhuan3744/article/details/78754614
(本文的第三部分为本人自己添加内容,算是看完博文的笔记)
MFC的多线程函数AfxBeginThread包含了两种版本,一种是工作者线程,一种是用户界面线程。本文主要讲解的是工作者线程的用法和提供一个实例。如果需要用户界面的用法,可以参考这篇文章http://www.cnblogs.com/lidabo/p/3489639.html。
一、工作者线程AfxBeginThread用法
1.1首先比较工作者线程函数和用户界面线程函数的异同
1.1.1工作者线程AfxBeginThread原型:(必看)
CWinThread*
AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
各个参数功能详解如下:
参数1:线程的入口函数,返回值一定为UINT,函数参数为:LPVOID,例如: UINT MyThreadFunction( LPVOID pParam );
参数2 :传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
参数3:指定线程优先级,如果为0,则与创建该线程的线程相同;
参数4:指定线程的堆栈大小,如果为0,则与创建该线程的线程相同;
参数5:创建标识,如果是CREATE_SUSPENDED,则在悬挂状态创建线程,在线程创建后线程挂起,否则线程在创建后开始线程的执行。
参数6:表示线程的安全属性,NT下有用。
1.1.2用户界面线程AfxBeginThread原型:(可以不看)
CWinThread*
AFXAPI AfxBeginThread(
CRuntimeClass* pThreadClass,
intnPriority,
UINTnStackSize,
DWORDdwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
各个参数功能详解如下:
参数1:是从CWinThread派生的RUNTIME_CLASS类;
参数2:指定线程优先级,如果为0,则与创建该线程的线程相同;
参数3:指定线程的堆栈大小,如果为0,则与创建该线程的线程相同;
参数4:是一个创建标识,如果是CREATE_SUSPENDED,则在悬挂状态创建线程,在线程创建后线程挂起,否则线程在创建后开始线程的执行。
参数5:表示线程的安全属性,NT下有用。
二、工作者线程AfxBeginThread函数用法实例
调用工作者线程AfxBeginThread函数的具体步骤如下所示:
2.1首先创建基于对话框的MFC工程后,在主对话框添加一个按钮控件(命名为打开线程),两个编辑框控件(功能是分别显示主线程状态和子线程状态),如下图所示:
2.2双击【打开线程】按钮函数,在按钮事件处理函数中,添加如下代码(可直接copy,修改一下两个对应编辑框ID和一个按钮ID就行)
if (ThreadFlag)
{
//关闭线程函数
ThreadFlag = FALSE;//线程标识一定要放在最前面,否则函数执行会出现莫名其妙错误!!!
GetDlgItem(IDC_BUTTON_TEST)->SetWindowTextA("打开线程");//AfxBeginThread线程的关闭,利用函数执行完毕后,自动返回,然后创建的线程也跟着关闭,对应资源也跟着释放。IDC_BUTTON_TEST按钮ID号,要修改成按钮上的ID号
return;
}
else
{
//创建线程函数
ThreadFlag = TRUE;//线程标识一定要放在最前面,否则函数执行会出现莫名其妙错误!!!
HANDLE hMultiThread = AfxBeginThread(ChildThread,
/*(LPVOID)*/this,
THREAD_PRIORITY_IDLE);//ChildThread线程函数入口(返回值为UINT,参数为LPVIOD
lParam) this入口点函数参数 THREAD_PRIORITY_IDLE设置优先级
参数4、5分别指定线程的堆栈大小(0:与参将线程相同)、创建标识(创建后悬挂CREATE_SUSPENDED或者立即执行)、安全属性,含义同用户界面线程
GetDlgItem(IDC_EDIT_MAIN)->SetWindowTextA("主线程开启");
//IDC_EDIT_MAIN主线程对话框ID号,要修改成自己的主线程对话框ID号
GetDlgItem(IDC_BUTTON_TEST)->SetWindowTextA("关闭线程");//IDC_BUTTON_TEST子线程对话框ID号,要修改成自己的子线程对话框ID号
return;
}
2.3在按钮函数的上面,添加如下代码:(可直接copy,修改一下对应编辑框ID就行)
UINT ChildThread(LPVOID
lParam)//多线程入口点函数,相当于另一个main,CPU或同时执行MFC的主线程和ChildThread线程函数
{
CMFCMultiThreadTest1Dlg* pDlg = (CMFCMultiThreadTest1Dlg*)lParam;//创建一个指向主对话框的句柄
CStringstr;
intThreadCound = 1;
while(pDlg->ThreadFlag)
{
str.Format(_T("子线程开启第%d次"),
ThreadCound++);//
pDlg->GetDlgItem(IDC_EDIT_CHILD)->SetWindowTextA(str);//设置子对话框显示str的内容,pDlg指向主对话框类入口点。编辑框和按钮控件都在主对话框上,所以可以通过获取主对话框类上的句柄,调用和修改主对话框上按钮控件类和编辑框类。IDC_EDIT_CHILD子线程编辑框的ID,需要修改为自己子对话框ID号
Sleep(1000);//定时1秒钟
}
return0;
}
2.4在主对话框Dlg头文件,加入如下代码:(注意:是创建工程主对话框下的头文件,带有Dlg的.比如我创建的工程命名为CMFCMultiThreadTest1Dlg,则主对话框头文件是CMFCMultiThreadTest1Dlg.h)
int ThreadFlag;//线程开启和关闭标志值,是全局变量
2.5在CMFCMultiThreadTest1Dlg::OnInitDialog()下面,添加如下代码:
ThreadFlag = FALSE;
三、函数编译执行后,得到的结果如下图所示:
程序运行后的图
点击【打开线程】按钮后的图
点击【关闭按钮】后的图
思路总结
首先,创建一个对话框
其次,在按钮触发事件中填入线程的开关判断,并附带线程的开关操作
最后,编写控制函数,实现线程中的具体功能