上一篇笼统介绍了如何创建线程以及线程如何和类成员函数通信,本篇将主要介绍:

线程的相关操作

1.线程的挂起和恢复:SuspendThread、ResumeThread

在线程创建并运行后,用户可以对线程执行挂起和恢复操作

挂起就是指暂停线程的执行,有暂停就有恢复,之后用户可以通过指定的操作来恢复线程的正常执行。

注意:线程的挂起和恢复是有次数限制的,可以进行多次挂起,但之后想要正常执行就需要多次恢复操作。

 //线程函数UINT __cdecl CThreadDlg::MyControllingFunction(LPVOID pParam){int tipMes = (int)pParam;CString strMsg;while (TRUE){strMsg.Format(_T("%d"), tipMes++);OutputDebugString(strMsg);Sleep(100);}return 100;}//定义一个线程句柄HANDLE hThread = NULL;//开启一个线程void CThreadDlg::OnBnClickedCreatethraedButton(){// TODO: 在此添加控件通知处理程序代码CWinThread* pThread = AfxBeginThread(MyControllingFunction, (LPVOID)123);hThread = pThread->m_hThread;//获得线程的句柄}void CThreadDlg::OnBnClickedSuspendthreadButton2(){// TODO: 在此添加控件通知处理程序代码SuspendThread(hThread);}void CThreadDlg::OnBnClickedResumethreadButton3(){// TODO: 在此添加控件通知处理程序代码ResumeThread(hThread);}

2.线程的相对优先级

线程的相对优先级总共有七个优先级,分别为:

  • THREAD_PRIORITY_TIME_CRITICAL           关键时间(最高)
  • THREAD_PRIORITY_HIGHEST                     最高,其实是次高
  • THREAD_PRIORITY_ABOVE_NORMAL       高于标准
  • THREAD_PRIORITY_NORMAL                    标准
  • THREAD_PRIORITY_BELOW_NORMAL      低于标准
  • THREAD_PRIORITY_LOWEST                      最低,其实是次底
  • THREAD_PRIORITY_IDLE                            空闲,最低

在AfxBeginThread创建的线程时候指定,而CreateThread可以在创建后在指定,可以通过下面两个函数进行设置:

获取:GetThreadPriority

设置:SetThreadPriority

设置线程优先级的目的:

1.cpu会以更多的的时间执行高优先级的线程

2.高优先级的线程可以打断低优先级的线程

3.线程的退出与终结

1.最好的方式:让线程函数主动退出,或者return;

可以保证线程函数里面的对象的析构函数被调用,以及线程申请的相关空间被释放;

2.线程自己主动退出,win32API可以调用ExitThread(MFC中使用AfxEndThread);

线程函数里面的对象的析构函数不会被调用,线程申请的相关空间被释放,所以,在c语言里可以使用该函数退出线程,但是c++不建议这样使用,因为c++有类,需要调用析构函数才能释放类的资源

3.其他程序的强行结束线程:

可以调用TerminateThread,此函数非常危险,

被结束的线程不会得到任何通知,线程申请的相关资源也不会被释放,所以谨慎使用。

4.线程退出码的获取:

GetExitCodeThread,前提是句柄有效,不被关闭。

在使用退出码时

HANDLE hThread = NULL;

DWORD dwExitCode = 0;

//开启线程,同时关闭自动释放线程,同时把句柄导出以此获取线程函数结束返回码

CWinThread* pThread = AfxBeginThread(StartCameraTest, NULL, THREAD_PRIORITY_NORMAL, 0, 0, NULL);

pThread->m_bAutoDelete = FALSE;//关闭自动释放资源的设置

hThread = pThread->m_hThread;//获取句柄

//获取线程函数的返回码

GetExitCodeThread(hThread, &dwExitCode);

//如果线程结束,返回码dwExitCode为100该值在线程函数最后return即可,值可以自己设定,但是有个限制,具体请查看文档,此时在释放线程句柄就安全了,同时把返回码初始成0

CloseHandle(hThread);

dwExitCode = 0;

线程间的通信

1.全局变量方式:

定义一个全局变量,开启两个线程,一个对变量进行自增操作,一个进行读取

//全局变量
int g_Num = 100;//写数据线程
UINT __cdecl CThreadDlg::ThreadWriteProc(LPVOID pParam)
{while (TRUE){++g_Num;Sleep(50);}return 100;
}//读数据线程
UINT __cdecl CThreadDlg::ThreadReadProc(LPVOID pParam)
{CString strMsg;while (TRUE){strMsg.Format(_T("%d"), g_Num);OutputDebugString(strMsg);Sleep(50);}}
//定义一个线程句柄
HANDLE hThread = NULL;//开启一个线程
void CThreadDlg::OnBnClickedCreatethraedButton()
{// TODO: 在此添加控件通知处理程序代码CWinThread* pThread = AfxBeginThread(ThreadWriteProc, NULL);   hThread = pThread->m_hThread;//获得线程的句柄AfxBeginThread(ThreadReadProc, NULL);}

这个是在同一个.cpp文件夹开启的两个线程和定义的两个全局变量,如果开启的线程在不同的.cpp文件下,如何申请全局变量呢?其实简单加入在1.cpp定义全局变量int a=100;在2.cpp中如何引用这个全局变量的a呢?只需在1.cpp的头文件1.h里加入extern int a;然后其它文件包含该头文件即可。

1.h

1.cpp

#include "1.h"

Int a = 100;

2.h

Extern int a;

2.cpp

#include "2.h"

直接可以使用全局变量a

2.多个线程都能看到的东西即类的成员

在类中声明如下:

public:CThreadDlg(CWnd* pParent = nullptr);        // 标准构造函数static UINT __cdecl MyControllingFunction(LPVOID pParam);static UINT __cdecl ThreadWriteProc(LPVOID pParam);static UINT __cdecl ThreadReadProc(LPVOID pParam);int m_Num;
//写数据线程
int g_Num = 100;
UINT __cdecl CThreadDlg::ThreadWriteProc(LPVOID pParam)
{CThreadDlg* pThis = (CThreadDlg*)pParam;while (TRUE){++(pThis->m_Num);Sleep(50);}return 100;
}//读数据线程
UINT __cdecl CThreadDlg::ThreadReadProc(LPVOID pParam)
{CThreadDlg* pThis = (CThreadDlg*)pParam;CString strMsg;while (TRUE){strMsg.Format(_T("%d"), (pThis->m_Num));OutputDebugString(strMsg);Sleep(50);}}
//定义一个线程句柄
HANDLE hThread = NULL;//开启一个线程
void CThreadDlg::OnBnClickedCreatethraedButton()
{// 初始化类中的变量m_Numm_Num = 0;//开启的线程是无法直接处理类中的变量的,需要传入类的地址。同时我们知道//该类的就是主对话框,因此直接把主对话框的地址;传给他即可,如:CWinThread* pThread = AfxBeginThread(ThreadWriteProc, this);   hThread = pThread->m_hThread;//获得线程的句柄AfxBeginThread(ThreadReadProc, this);}

3.发消息的方式:PostThreadMessage

该方式需要自定义消息,和绑定,然后一个线程进行消息的发送,另一个线程不停的等待消息和筛选消息类型即只接收我们自定义的消息,一旦接收到立马执行,整体流程是这样的,因为还没深入学习MFC编程,所以这里先放放,以后用到了在系统的总结,但是总体思路是这样的

4.与界面线程相联系

1.创建界面线程的返回值CWinThread类型指针,就是新线程的指针,也因此可以通过强制类型转换对先创建的界面线程进行赋值和信息传递,这里大家需要调试一下。因为界面线程的是没有参数传递,那怎么才能把值传递给新的线程呢?就是通过强制类型的转换:

class CUIThreadApp :public CWinThread
{
public:int num;
};CWinThread* pThread = AfxBeginThread(RUNTIME_CLASS(CUIThreadApp), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);((CUIThreadApp*)pThread)->num = 456;

在初始程序中就好创建这个类的对象,然后类成员的变量num就为456.

这里是通过主线程向子线程进行传递信息,如何在子线程中获取主线程的信息呢

2.在新界面线程中调用AfxGetApp();获取到的是主线程的指针,通过强制类型转换就可以获取主线程的信息了。

3、通过PostThreadMessage方式进行通信,界面线程同样适用,重载界面线程类的PreTranslateMessage即可

以上就是线程间的通信

VC++中多线程学习(MFC多线程)二(线程的相关操作、线程间的通信)相关推荐

  1. VC++中多线程学习(MFC多线程)一(线程的创建、线程函数如何调用类成员呢?如何调用主对话框的成员?、MFC中的工作线程和界面线程的区别)

    这里废话不多讲了,因为项目原因,需要开启线程进行处理,在不了解线程的情况下,直接百度一下,然后就使用了,结果可想而知,出现了异常,所以花了一天时间系统学习一下多线程,这里主要是针对win32编程方面的 ...

  2. VC++中多线程学习(MFC多线程)三(线程同步包含:原子互锁、关键代码段、互斥器Mutex、Semaphores(信号量)、Event Objects(事件))

    目录 ​​​​​​​​​​​​ 线程同步的必要性: 2.解决同步问题的方法 2.1原子互锁家族函数 2.2Critical Sections(关键代码段.关键区域.临界区域) 2.3 互斥器Mutex ...

  3. C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  4. 【JAVA多线程学习笔记】(1)实现线程的方式 线程生命周期 操作线程的方法

    文章目录 两种方式实现线程 继承Thread类 模拟银行叫号的程序 Runnable接口 代码1:(与swing相结合创建gui程序) Thread类的⼏个常⽤⽅法 线程生命周期 操作线程的方法 代码 ...

  5. C#多线程学习(五) 多线程的自动管理(定时器) (转载系列)——继续搜索引擎研究...

    Timer类:设置一个定时器,定时执行用户指定的函数.               定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer ...

  6. C#多线程学习(一) 多线程的相关概念(转自xugang的blog)

    C#多线程学习(一) 多线程的相关概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 什么是线程? 线程 ...

  7. [转载]C#多线程学习(一) 多线程的相关概念

    原文地址:http://www.cnblogs.com/xugang/archive/2008/04/06/1138856.html 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中 ...

  8. 如何在VC中加减日期及 CTime COleDateTime的常用操作和比较

    如何在VC中加减日期及 CTime COleDateTime的常用操作和比较 [转贴 2008-10-31 15:51:28]     字号:大 中 小 如何在VC中加减日期  使用CTime类,如: ...

  9. [转]C#多线程学习(四) 多线程的自动管理(线程池)

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

最新文章

  1. Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)
  2. 在ASP.NET中将图片存储到Sql Server数据库中
  3. ClamAV病毒库增加特征码
  4. ElasticSearch学习笔记-02集群相关操作_cat参数
  5. 深入理解Linux异步I/O框架 io_uring
  6. 从去除毛刺的策略看开运算opening_circle和闭运算closing_circle的异同
  7. python编程中条件句_简单讲解Python编程中namedtuple类的用法
  8. C#LeetCode刷题之#202-快乐数(Happy Number)
  9. Leetcode每日一题:904.fruit-into-baskets(水果成篮)
  10. Mac版MySQL安装和登陆
  11. dwm1000 用c语言控制,DWM1000 测距原理简单分析(示例代码)
  12. 聊天机器人之知识图谱 Freebase 简介
  13. js简单实现根据身份证号码识别性别年龄生日
  14. android 联机游戏平台,游聚平台/街机平台/主机联网/街机对战平台/网络街机
  15. 传播正能量——《海南英才》阅读的读后感2200字
  16. 使用信用卡 要避开这些陷阱
  17. html5页面嵌入视频播放,使用HTML5在网页中嵌入音频和视频播放的基本方法
  18. 深入Android系统(二)Bionic库
  19. 如何使用ssh连接windows?
  20. 名编辑电子杂志大师教程 | 书本打开密码

热门文章

  1. wordpress插件列表
  2. 手把手教你设计交友网站【3】
  3. Python学习笔记(四)—生成随机数
  4. 数据分析的五个阶段及价值
  5. 江西 高职 分数 计算机,快讯!江西高职(专科)批次各高校投档分数线出炉…...
  6. gdt描述_GDT全局描述符表
  7. 机器人水库涵洞检测_管渠清淤机器人、管道浑水探测机器人……想不到吧?哈排水集团竟然是“科研达人”...
  8. 笔记︱决策树族——梯度提升树(GBDT)
  9. Ext2 中如何换行 布局?
  10. 使用HTML5的语义标签