C++ 关于MFC多线程编程的注意事项_C 语言

在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread  来创建一个工作线程,看一下这个函数的说明:

复制代码 代码如下:

CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
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,0,(LPARAM)&str);
    return 0;
}

在这个函数中,我们要运行由此函数组成的一个线程的话,就需要传递一个参数lpParam,而这个参数是由 Param 的结构体来指定。实际上是传递了三个参数进去。

复制代码 代码如下:

Param* par;
par = (Param*)lpParam;

我们会用上在的强制类型转换的方法,就可以还原参数的值。根据这三个参数就  自定主的线程函数就可以运行了。那如何通知界面线程呢。看一下自定义函数里面的这一句

hander->SendMessage(WM_USERMESSAGE,0,(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 0;

}

这段程序是根据得到的传递过来的参数,在界面上显示具体的参数内容。

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
多线程编程
多线程编程注意事项、mfc多线程编程实例、mfc多线程编程、mfc多线程编程csocket、mfc socket多线程编程,以便于您获取更多的相关知识。

时间: 2024-08-03 14:53:43

C++ 关于MFC多线程编程的注意事项_C 语言的相关文章

C++ 关于MFC多线程编程的注意事项

  这篇文章主要介绍了C++ 关于MFC多线程编程的注意事项的相关资料,需要的朋友可以参考下 在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread 来创建一个工作线程,看一下这个函数的说明: 代码如下: CWinThread* AFXAPI AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize =

C++多线程编程时的数据保护_C 语言

 在编写多线程程序时,多个线程同时访问某个共享资源,会导致同步的问题,这篇文章中我们将介绍 C++11 多线程编程中的数据保护.数据丢失 让我们从一个简单的例子开始,请看如下代码:   #include <iostream> #include <string> #include <thread> #include <vector> using std::thread; using std::vector; using std::cout; using std

c语言socket多线程编程限制客户端连接数_C 语言

先上一些多线程需要使用的函数定义: 复制代码 代码如下: DWORD WINAPI ProcessClientRequests(LPVOID lpParam)  //新线程将会执行的函数定义{      return 0;} HANDLE handler=CreateThread(NULL, 0, ProcessClientRequests, &clientsocket, 0, NULL);   //这里比较简单,&clientsocket是个指针,是从主线程传入新线程的参数 WaitFo

c#.net多线程编程教学——线程同步_C#教程

随着对多线程学习的深入,你可能觉得需要了解一些有关线程共享资源的问题. .NET framework提供了很多的类和数据类型来控制对共享资源的访问. 考虑一种我们经常遇到的情况:有一些全局变量和共享的类变量,我们需要从不同的线程来更新它们,可以通过使用System.Threading.Interlocked类完成这样的任务,它提供了原子的,非模块化的整数更新操作. 还有你可以使用System.Threading.Monitor类锁定对象的方法的一段代码,使其暂时不能被别的线程访问. System

浅析C++编程当中的线程_C 语言

线程的概念 C++中的线程的Text Segment和Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到.除此之外,各线程还共享以下进程资源和环境:     文件描述符     每种信号的处理方式     当前工作目录     用户id和组id 但是,有些资源是每个线程各有一份的:     线程id     上下文,包括各种寄存器的值.程序计数器和栈指针     栈空间     errno变量     信号屏蔽字     调度

C/C++ 多线程的学习心得总结_C 语言

个人觉得在学习多线程编程之前最好先了解进程和线程的关系, 然后在学习线程工作方式的过程中动手写个(我是从抄开始的)多线程的小程序, 会对学习多线程有很大的帮助, 否则只有理论是很抽象的. 在学习多线程编程之前, 必须先知道什么是 线程函数, 线程函数就是另一个线程的入口函数. 默认情况下一个我们所写的代码都是只有一个线程的, 而这个线程的入口函数就是main() 函数, 这是系统默认的. 而我们创建的另一个线程也需要一个函数来进入, 这个函数就叫做线程函数. 在C/C++中, 可以调用 '运行期

c++中struct使用注意事项_C 语言

1.C++的结构体变量在声明的时候可以省略struct,在c中这样是不可以的,例子如下 #include<iostream> #include<string> using namespace std; struct test{ int num; string name; }; int main(void) { test t; t.num=1; t.name="jack"; cout<<t.num<<" "<<

C语言中while与do-while的介绍与注意事项_C 语言

一.while和do-while的简介  1). while语句  语法:  while(表达式){  循环体;  } 循环过程:  1.先判断表达式,是否为真,如果为真跳转到2,否则跳转到3  2.执行循环体,执行完毕,跳转到1  3.跳出循环 2). do-while语句 语法:  do{  循环体;   }while(表达式);  注意:这个while后面的小括号必须接; 循环过程:  1.先执行循环体,执行完毕跳转到2  2.判断表达式的结果是否为真,如果为真,跳转到1,否则跳转到3  

举例解析设计模式中的工厂方法模式在C++编程中的运用_C 语言

工厂方法模式不同于简单工厂模式的地方在于工厂方法模式把对象的创建过程放到里子类里.这样工厂父对象和产品父对象一样,可以是抽象类或者接口,只定义相应的规范或操作,不涉及具体的创建或实现细节. 其类图如下: 实例代码为: #pragma once class IProduct { public: IProduct(void); virtual ~IProduct(void); }; #pragma once #include "iproduct.h" class IPad : public