C++ 如何在类中创建线程
问题描述:
一般我们在启线程时,都是把线程函数写成全局函数来使用,但是如果要把线程操作写成类,线程函数放在类里面在C++编译会不通过。
在C++类中创建线程会有报错:
下面以一个简单的类进行举例
EXTERNAL.h文件
#ifndef _RADIO_EXTERNAL_H_
#define _RADIO_EXTERNAL_H_
class CRadioTask : public CTaskBase
{
public:
CRadioTask();
virtual ~CRadioTask();
virtual int Run();
int WriteNetMessage(BYTE *pBuffer, USHORT uLen);
private:
BYTE m_line_id;
BYTE m_ConnectStatus; ////0-断开,1-连接
BYTE m_sendFlag; //0-未发送,1-已发送
};
#endif
在EXTERNAL.cpp文件的成员函数中直接创建线程会导致编译不通过
int CRadioTask::Run()
{
OsBeginTask( &m_ThreadId, WriteNetMessage,NULL);
return 0;
}
int CRadioTask::WriteNetMessage(BYTE *pBuffer, USHORT uLen)
{
int iReVal = 0;
if(m_ConnectStatus)
{
iReVal =OsWriteSocket(m_SocketId, pBuffer, uLen, &uLen);
if(iReVal)
{
sysprint(0, 0, "[%s] OsWriteSocket error rc=%d", m_TaskName, iReVal);
CloseSocket();
}
}
return iReVal;
}
编译不通过
原因分析:
在创建线程的api 中传入的线程函数需要在编译时确定地址,如果是普通的类函数,编译时不能确定地址,需要创建类的对象才能获取。把线程的执行函数写成static 函数,或者是全局函数,函数地址在编译时是确定的
解决方案一:
当WriteNetMessage为成员函数时,CRadioTask 继承CTaskBase类的创建线程函数,在CTaskBase类中将线程的执行函数TaskFunc定义为静态函数。
在类中定义线程函数,但是需要将线程函数定义为静态的。
class CTaskBase
{
public:
CTaskBase() : m_ThreadId(0)
{};
virtual ~CTaskBase() {};
//线程启动
int start()
{
OsBeginTask( &m_ThreadId, TaskFunc, (void *)this );
return 0;
}
protected:
THREAD_ID m_ThreadId;
//将线程的执行函数定义为静态类
static int TaskFunc(void *lpParam)
{
CTaskBase *pThis = (CTaskBase *)lpParam;
return pThis->Run();
}
virtual int Run() = 0;
};
//CRadioTask 继承 CTaskBase
class CRadioTask : public CTaskBase
{
public:
CRadioTask();
virtual ~CRadioTask();
virtual int Run();
private:
BYTE m_line_id;
BYTE m_ConnectStatus; ////0-断开,1-连接
BYTE m_sendFlag; //0-未发送,1-已发送
};
// main.cpp
int main()
{
CRadioTask* PTask=new CRadioTask();
PTask->start(); //创建线程成功
sleep(20);
return 0;
}
解决方案二:
当WriteNetMessage为全局函数时,
将要传入线程的函数,写成全局函数,不作为类的成员;然后把类的实例(pTask)作为参数传入线程中要调用的函数(WriteNetMessage),这样就可以调用类中的成员函数和变量(m_TaskName,m_ConnectStatus)了。
int WriteNetMessage(CRadioTask* pTask,BYTE *pBuffer, USHORT uLen)
{
int iReVal = 0;
if(pTask->m_ConnectStatus)
{
iReVal = OsWriteSocket(m_SocketId, pBuffer, uLen, &uLen);
if(iReVal)
{
sysprint(0, 0, "[%s] OsWriteSocket error rc=%d", pTask->m_TaskName, iReVal);
CloseSocket();
}
}
return iReVal;
}
int CRadioTask::Run()
{
OsBeginTask( &m_ThreadId, WriteNetMessage,NULL);
return 0;
}
参考:https://tnie.github.io/2016/11/03/multiThread/
2548

被折叠的 条评论
为什么被折叠?



