C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理
在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread 来创建一个工作线程,看一下这个函数的说明:
CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = ,
DWORD dwCreateFlags = ,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
在这个说明中,除第1和第2两个参数外,余下的参数都有默认值。所以,我们在使用的时候,是必须要指定前两个参数的。
其中 第一个参数是 要运行的函数的名称,光写函数名就可以了,不能加引号。
第二个参数,是指定 运行函数的 参数,这个参数的类型为 LPVOID 。所以要运行的函数的在传递过去后,要转化为LPVOID类型才可以。
而要运行的参数还有一个限制,那就是必须返回一个UINT类型的结果。所以要运行的函数的就有一个基本上固定的格式。
UINT RunProce(LPVOID lpParam)
在这里还需要特别说明一下,这个函数不能是实例函数,也就是函数前面是不能有 类限定符:: 的。如果是静态函数也是可以的。
在这个函数中,我们只能使用一个参数,而参数的类型只能是 LPVOID ,可以用一个结构体来封闭多个参数。
余下的问题,就不是很多了。
关于 多线程,就写到这里吧!
在多线程编程中,一个很重要的问题就是,要将线程的运行过程通知界面线程,做一些显示方面的更新。如下载线程,在适当的时候,可以更新界面,现在下载到什么进度了。等等的情况。但是在工作线程中,是不是直接操作界面线程的控件的。那怎么办呢,只能通过自定义一个消息来解决。
工作流程,就是 在自定义线程中 通过发送一个界面上的 消息,来通知界面做一些更新操作。在这个自定义消息中,有一个细节要解决,那就是自定义消息,必须要指定接收消息的控件句柄。当然你中以使用m_pApp 直接通知主框架来解决,但是这样解决似乎绕了一个很大的圈。其实解决的方法很简单,那就是直接将接收消息的控件的句柄传给自定义线程,就可以了。我们直接在线程中使用此句柄就可以解决了。
我们知道控件的基类都是 CWnd。所以我们传递一个CWnd的指针进去。当然还有一些其它的参数要一块传递进去,那就做一个结构吧
typedef struct{
CString srcString;
CString DesString;
CWnd* hander;
}Param;
这里我们传递了三个参数 两个字符串一个指针。
我们先造一个自定义线程函数
UINT RunProce(LPVOID lpParam)
{
Param* par;
CWnd* hander;
par = (Param*)lpParam;
hander = par->hander;
myCopyDirectory(lpParam); CString str;
str = "复制完成"; hander->SendMessage(WM_USERMESSAGE,,(LPARAM)&str); return ;
}
在这个函数中,我们要运行由此函数组成的一个线程的话,就需要传递一个参数lpParam,而这个参数是由 Param 的结构体来指定。实际上是传递了三个参数进去。
Param* par;
par = (Param*)lpParam;
我们会用上在的强制类型转换的方法,就可以还原参数的值。根据这三个参数就 自定主的线程函数就可以运行了。那如何通知界面线程呢。看一下自定义函数里面的这一句
hander->SendMessage(WM_USERMESSAGE,,(LPARAM)&str);
这一句中 hander 是由结构体转换而来的 接收消息的控件的句柄。然后调用这个控件的 SendMessage 方法,就可以向此控件发消息了。消息的内容由后面的参数来决定
第一个参数 WM_USERMESSAGE 这是一个消息的名称。这个名称实际上是一个数字。我们需要在 .h 文件中 指定一下如下面的格式
#define WM_USERMESSAGE 11130
后面的数字造的大一点,哈哈
第二个与第三个参数,就是这个消息传递具体的值,如果不需要传递值的话,那就直接写0吧
在这里我们想在传递参数的第三个参数上传递一个 字符串,那就是上面的写法了。
这样的话,在线程中发送消息的部分,就全部讲完了。消息发送出去了,怎么接收呢?
这真是一个重要的问题
首先,要将消息做一下映射。消息映射的目的,就是告诉程序,当出现这个消息的时候,使用哪个函数进行处理。这样的话,就首先需要一个消息映射的函数。这个消息映射的函数不是乱写,因为要传递两个参数,所以这个函数需要能够接收这两个参数。处理函数一般这样子写
LRESULT CCopyfileDlg::OnProcName(WPARAM wParam, LPARAM lParam)
他奶奶的,太神奇了。返回值只能是 LRESULT 。这个不用讨论吧,照着抄吧。函数名称后面有参数两个,这是一个实例函数。因为前面有::
两个参数一般也写成这个样子的。
函数内容,就由你的程序的功能决定了。我这里直接抄一段我自己的代码吧
LRESULT CCopyfileDlg::OnProcName(WPARAM wParam, LPARAM lParam)
{
// TODO: 处理用户自定义消息
CString* str = (CString*)lParam;
SetDlgItemText(IDC_STATIC,*str); if(*str == "复制完成")
{
(CButton*)GetDlgItem(IDC_COPYBUT)->EnableWindow(true);
} return ; }
这段程序是根据得到的传递过来的参数,在界面上显示具体的参数内容。
SetDlgItemText(IDC_STATIC,*str); //在静态文本框中显示消息。
备注:
如果要让按钮变成灰色的,那就使用控件的 EnableWindow 方法。
这个方法,我们说,是专门的消息处理函数,那么它的声明也比较特殊。需要这么写
afx_msg LRESULT OnProcName(WPARAM wParam, LPARAM lParam);
将上面的内容放在 h文件的合理位置就可以了。
现在消息处理函数也有了。但是怎么将映射呢?
其实在 CPP文件中,有一个由 BEGIN_MESSAGE_MAP(CCopyfileDlg, CDialog) 和END_MESSAGE_MAP() 包括的区域。这个区域就是用来定义消息映射的。
将这么一句话放在他们中间,就OK了
ON_MESSAGE(WM_USERMESSAGE,OnProcName)
这么一句话,就将 WM_USERMESSAGE 与 OnProcName 与消息处理函数结合在一起了。是不是超级简单呀!
这样我们的界面线程中的消息处理部分也主做好了。
当消息发送过来后,就会通过消息映射放在对应的函数中加以处理。
C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理的更多相关文章
- 关于python多线程编程中join()和setDaemon()的一点儿探究
关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的 ...
- Java多线程编程中Future模式的详解
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Java多线程编程中Future模式的详解<转>
Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...
- Qt多线程编程中的对象线程与函数执行线程
近来用Qt编写一段多线程的TcpSocket通信程序,被其中Qt中报的几个warning搞晕了,一会儿是说“Cannot create children for a parent that is in ...
- Java多线程编程(2)--多线程编程中的挑战
一.串行.并发和并行 为了更清楚地解释这三个概念,我们来举一个例子.假设我们有A.B.C三项工作要做,那么我们有以下三种方式来完成这些工作: 第一种方式,先开始做工作A,完成之后再开始做工作B ...
- C#多线程编程中的锁系统
C#多线程编程中的锁系统(二) 上章主要讲排他锁的直接使用方式.但实际当中全部都用锁又太浪费了,或者排他锁粒度太大了. 这一次我们说说升级锁和原子操作. 目录 1:volatile 2: Inter ...
- 【C/C++开发】多线程编程中的join函数
多线程编程中的join函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # coding: utf-8 # 测试多线程中join的 ...
- 多线程编程中的EventWaitHandler
首先如果读者是.Net多线程编程的老手,就不用看这篇文章了,这篇文章主要是阐述EventWaitHandler的一些基本原理和用法. 在.NET的System.Threading命名空间中有一个名叫W ...
- Linux下多线程编程中信号量介绍及简单使用
在Linux中有两种方法用于处理线程同步:信号量和互斥量. 线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保 ...
随机推荐
- (转)C# WebApi 接口参数不再困惑:传参详解
原文地址:https://www.cnblogs.com/landeanfen/p/5337072.html 本篇打算通过get.post.put.delete四种请求方式分别谈谈基础类型(包括int ...
- android Keycode 完全对照表
input keyevent 82 menuinput keyevent 3 homeinput keyevent 19 upinput keyevent 20 downinput keyevent ...
- tp5 post接到的json被转义怎么解决???
$data =input('post.');//用户唯一标识$goods = $data['goods']; $shopcuxiao=$data['shopcuxiao']; $goods=htmls ...
- es6基础(2)--解构赋值
//解构赋值 { let a,b,rest; [a,b]=[1,2]; console.log(a,b); } //数组解构赋值 { let a,b,rest; [a,b,...rest]=[1,2, ...
- asp.net 中日期的格式化显示的方法
在Asp.net 中经常使用日期,在不同的场合,对日期的显示方式有不同的要求,为此,自己总结了一些日期格式化的方式,仅供学习参考使用: C#格式化日期时间 DateTime dt = DateTime ...
- Nginx的安装(CentOS 7环境)
安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境. 一. gcc 安装安装 nginx 需要先 ...
- python-异常
实例:https://www.cnblogs.com/tangpg/p/7992979.html 在系统内部,解释器使用一种被称为 ‘块栈’的结构处理异常逻辑.它和执行栈一起被栈帧管理.块栈在运行期间 ...
- 《算法》第六章部分程序 part 5
▶ 书中第六章部分程序,包括在加上自己补充的代码,网络最大流 Ford - Fulkerson 算法,以及用到的流量边类和剩余流量网络类 ● 网络最大流 Ford - Fulkerson 算法 pac ...
- 《算法》第六章部分程序 part 4
▶ 书中第六章部分程序,包括在加上自己补充的代码,利用后缀树查找最长重复子串.查找最大重复子串并输出其上下文(Key word in context,KWIC).求两字符串的最长公共子串 ● 利用后缀 ...
- Mybatis七(MBG 逆向工程)
官方地址:http://www.mybatis.org/generator/ https://github.com/mybatis/generator/releases <1>编写mbg. ...