前言:
作为一名刚出道的学生,可能在工作中会遇到好多好奇的知识,而这些知识有没有开源,可能使用起来底气没有那么足。
其实 这些所有的已封装的东西,都是对最基础(底层)的函数库的调用与封装。自己动手实现对某个功能的封装,不仅可以
很好的了解到其内部实现的方式,同时也加深对知识的认知程度,还可以对以后的程序设计的模块化(面向对象的编程思想)
有所认识。
内容:
好了废话不多说了,直接上代码了(封装的线程)
头文件:
#ifndef _H_T_BASE_H_
#define _H_T_BASE_H_
#include<windows.h>
class CTBase
{
public:
typedef enum
{
TBRUNNING = 0, //不挂起
TBSUSPEND = 4 // 挂起
}CREATEFLAG;
public:
CTBase();
virtual ~CTBase();
public:
bool TBCreateThread(CREATEFLAG createFlag);
bool TBDestroyThread();
bool TBBeginThread();
bool TBEndThread();
bool TBSuspendThread();
bool TBResumeThread();
void GetThreadID(unsigned &threadID);
void SetStop(bool bStop);
bool GetStop();
private:
static unsigned _stdcall TBTFunc(void *pThis);
virtual bool TBRun() = 0;
private:
HANDLE hTHandle;
unsigned uThreadID;
bool m_bStop;
};
#endif
源文件:
#include "TBase.h"
#include <process.h>
CTBase::CTBase()
{
hTHandle = NULL;
m_bStop = false;
}
CTBase::~CTBase()
{
}
bool CTBase::TBCreateThread(CREATEFLAG createFlag)
{
if(hTHandle != NULL)
return false;
hTHandle = (HANDLE)_beginthreadex(NULL,
0,
CTBase::TBTFunc,
this,
createFlag,
&uThreadID);
if(hTHandle == NULL)
return false;
return true;
}
bool CTBase::TBDestroyThread()
{
<span style="white-space:pre"> </span>CloseHandle(hTHandle);
_endthreadex(0);
return true;
}
bool CTBase::TBBeginThread()
{
return true;
}
bool CTBase::TBEndThread()
{
return true;
}
bool CTBase::TBSuspendThread()
{
unsigned long nResult = SuspendThread(hTHandle);
if(nResult == -1)
return false;
return true;
}
bool CTBase::TBResumeThread()
{
unsigned long nResult = ResumeThread(hTHandle);
if(nResult == -1)
return false;
return true;
}
unsigned _stdcall CTBase::TBTFunc(void *pThis)
{
CTBase *pTBase = (CTBase*)(pThis);
pTBase->TBBeginThread();
while(!pTBase->m_bStop)
{
pTBase->TBRun();
}
pTBase->TBEndThread();
return 0;
}
void CTBase::GetThreadID(unsigned &threadID)
{
threadID = uThreadID;
}
void CTBase::SetStop( bool bStop )
{
m_bStop = bStop;
}
bool CTBase::GetStop()
{
return m_bStop;
}
(1) 关于多线程的创建
创建方式有3中:
1.
CreateThread () 函数 属于操作系统级别的(不提倡使用)
2.
_beginthread () 和 _beginthreadex() 属于语言级别的 其内部会调用CreateThread 函数,但调用之前会做其他的额外工作
3. AfxBeginThread() 该函数属于平台级别的(只限于Microsoft 提供的集成开发环境VS),其可以创建界面线程和工作线程两种。
终止线程的方法:
1. 最好的方法是让线程自己执行玩,自动退出
2.ExitThread(HANDLE) 退出
3.TerminateThread(HANDLE)强制退出线程
4.通过调用终止进程,间接地终止线程
5.对于_beginthread() 和_beginthreadex() 创建的线程,应使用配套的函数去终止线程,其函数为
_endthread() 和 _endthreadex()
在退出线程时,要手动去释放掉一些资源比如 线程句柄。
下面是一个关于线程退出时,调用不同函数所做的事情:
关于界面线程:
界面线程是MFC中一个特殊的线程,其有自己的消息循环机制,而工作线程只是关心要做的事情。
(2)关于虚函数
在上述类中,使用到了一个关键字(virtual) ,该关键字是虚函数的标志。
上述的虚函数属于纯虚函数,引起满足纯虚函数的定义
virtual bool TBRun() = 0;
含有纯虚函数的类,是不能够声明类对象的
虚函数是c++动态链编的一中实现方式(重写),
其静态链编的方式是 函数的重载 (重载)。
这两种方式都是c++实现多态的方式,
只不过函数重载在编译时就已经确定调用那个函数,
而函数的重写,是在程序运行时,在确定调用那个函数
其实函数的重写,类似于一种私人订制,他提供给你一个画板,如果你想改变一下画板的内容,就自己动手,
画上自己想画的内容,在执行时,就按照你的意愿进行。
一个大神的作品,关于虚函数在每个类对象中的内存存储及存储方式: