基于MFC的多线程编程实例

本文详细介绍MFC中AfxBeginThread函数的使用方法,包括工作者线程与用户界面线程的区别,通过实例演示如何创建与控制线程,实现线程间的通信。
摘要由CSDN通过智能技术生成

————————————————
版权声明:本文为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;

三、函数编译执行后,得到的结果如下图所示:
程序运行后的图
在这里插入图片描述
点击【打开线程】按钮后的图

在这里插入图片描述
点击【关闭按钮】后的图
在这里插入图片描述

思路总结

首先,创建一个对话框
其次,在按钮触发事件中填入线程的开关判断,并附带线程的开关操作
最后,编写控制函数,实现线程中的具体功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值