怎么用类的非静态成员函数作为线程回调函数?求高手指点

旅客 2013-09-28 09:12:59
我的代码是这样的
#include "windows.h"
#include <process.h>
#include "iostream"
using namespace std;

class Test{
public:
static DWORD WINAPI mThread(PVOID lpParam);
void ThreadPROC(void* pParam);
int CallThread();
private:
static int i;
int j;
};
int Test::i = 0;

DWORD Test::mThread(PVOID pParam)
{
Test* p = (Test*)pParam;
p->i = 1;
OutputDebugString(L"线程执行\n");
return 0;
}

void Test::ThreadPROC(void* pParam){}

int Test::CallThread()
{
//使用静态成员函数作为线程函数
DWORD ThreadID = 1;
HANDLE hThread = CreateThread(0 , 0, &Test::mThread, this, 0, &ThreadID);
if (hThread == NULL)
{
MessageBox(NULL, L"线程创建失败", NULL, NULL);
}

//不使用静态成员函数作为线程函数
union{
void (_USERENTRY * ThreadProc)(void*);
void(_USERENTRY Test::*MemoryProc)(void*);
}proc;
proc.MemoryProc = &Test::ThreadPROC;
_beginthread(proc.ThreadProc, 0, this);
return 0;
}

int main()
{
Test t;
t.CallThread();
while (1)
{
}
return 0;
}
_USERENTRY 也不知道是什么东西,在网上查不到
编译后好多错误
...全文
432 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaohuh421 2013-10-02
  • 打赏
  • 举报
回复
引用 13 楼 xiaohuh421 的回复:
[quote=引用 9 楼 sl8023dxf 的回复:] 那除了楼上的封装一个线程类以外,还有什么其他方法吗 其实静态的可以,就是不想做什么都要用一个指针指一下,太麻烦了
也可以达到不用指针的方法啊, 只是说会多一个函数. 类似这样: class MyClass { static UINT WINAPI threadFun(void *pVoid) //此函数只作中转. { MyClass *pThis = (MyClass*)pVoid; pThis->FunProc(); } void FunProc() { //这是一个非静态成员函数, 作实际线程需要的代码. } } [/quote] 线程函数忘记 写return了
xiaohuh421 2013-10-02
  • 打赏
  • 举报
回复
引用 9 楼 sl8023dxf 的回复:
那除了楼上的封装一个线程类以外,还有什么其他方法吗 其实静态的可以,就是不想做什么都要用一个指针指一下,太麻烦了
也可以达到不用指针的方法啊, 只是说会多一个函数. 类似这样: class MyClass { static UINT WINAPI threadFun(void *pVoid) //此函数只作中转. { MyClass *pThis = (MyClass*)pVoid; pThis->FunProc(); } void FunProc() { //这是一个非静态成员函数, 作实际线程需要的代码. } }
旅客 2013-10-01
  • 打赏
  • 举报
回复
好吧,看来只能暂时先用静态成员函数来做了,不过11楼的说法,可以试试 不过,现在C++11标准,完全支持的编译器好像没有吧
lm_whales 2013-10-01
  • 打赏
  • 举报
回复
定义一个线程抽象类 定义一个运行虚函数 抽象类实现 静态线程函数。 这个类实现线程启动函数,调用静态线程函数,传递线程参数是this 指针。 然后定义一个实现类,继承那个线程类就可以了。 所有继承的类都不需要再实现静态线程函数了 也可以采用模板来实现 C++11 的线程类,当然也很不错 另外C++的函数对象可以把,非静态函数转换为,类似全局函数的方式调用。
passion_wu128 2013-09-30
  • 打赏
  • 举报
回复
成员函数调用使用的是__thiscall调用约定 而_beginthread 原型为 unsigned long _beginthread( void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist ); 使用的是__cdecl调用约定,肯定不能混用啊。 即使最后通过非常特殊调用成功了,也是很容易出现异常的。
cad_vc 2013-09-30
  • 打赏
  • 举报
回复

#ifndef _XTHREAD_INCLUDED_
#define _XTHREAD_INCLUDED_

#if defined(WIN32)

#include <windows.h>

#define  DEFAULT_STACK_SIZE       0
#define  DEFAULT_THREAD_PRIORITY  0

#define MS_VC_EXCEPTION 0x406D1388

typedef struct tagTHREADNAME_INFO
{
	DWORD dwType; // Must be 0x1000.
	LPCSTR szName; // Pointer to name (in user addr space).
	DWORD dwThreadID; // Thread ID (-1=caller thread).
	DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;


class CThread  //线程类
{
private:
	HANDLE m_hThread;                             //线程句柄
	int    m_nThreadPriority;
	DWORD  m_dwThreadStackSize;
	
private:
	static DWORD WINAPI ThreadBody(LPVOID pParam)
	{
		if (!pParam)
			return DWORD(-1);
		
		CThread *pThis = (CThread *)pParam;
		pThis->SetThreadName(-1, "win-thread");
		return pThis ->Run();		
	}

	void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName)
	{
		THREADNAME_INFO info;
		info.dwType = 0x1000;
		info.szName = szThreadName;
		info.dwThreadID = dwThreadID;
		info.dwFlags = 0;
		
		__try
		{
			RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
		}
		__except(EXCEPTION_CONTINUE_EXECUTION)
		{
		}
	}
	
protected:	
	virtual DWORD Run() = 0;
	
public:		
	CThread(HANDLE hThread=NULL, 
		    int nThreadPriority=DEFAULT_THREAD_PRIORITY, 
			DWORD dwThreadStackSize=DEFAULT_STACK_SIZE) 
			:m_hThread(hThread), m_nThreadPriority(nThreadPriority), m_dwThreadStackSize(dwThreadStackSize){};
	
private:
    
    // 禁止拷贝构造函数。
    CThread(const CThread&);
	// 禁止赋值操作符。
    void operator=(const CThread&);
	
public:
	
	BOOL Start() //创建线程并启动
	{   
		if (m_hThread)
			return FALSE;
		
		m_hThread = ::CreateThread(NULL, m_dwThreadStackSize, (LPTHREAD_START_ROUTINE)CThread::ThreadBody, (LPVOID)this, 0, NULL);

		if (NULL != m_hThread)
			return FALSE;

		if (abs(m_nThreadPriority) > THREAD_BASE_PRIORITY_MAX && m_nThreadPriority != THREAD_PRIORITY_TIME_CRITICAL)
		{
			m_nThreadPriority = 0;
		}

		::SetThreadPriority(m_hThread, m_nThreadPriority);
		
		return TRUE;		
	}
	
	void Join() //等待线程退出
	{ 
		::WaitForSingleObject(m_hThread,INFINITE);
	}

	DWORD SuspendThread()
	{
		return ::SuspendThread(m_hThread);
	}

	DWORD ResumeThread()
	{
		return ::ResumeThread(m_hThread);
	}
	
	void KillThread()
	{
		::TerminateThread(m_hThread, -1);
		m_hThread = NULL;
	}
	
	BOOL IsAlive() 
	{
		
        if(NULL == m_hThread) 
		{
            return FALSE;
        }
		
        DWORD dwRes = ::WaitForSingleObject(m_hThread, 0);
        
        if(WAIT_TIMEOUT == dwRes) 
		{
            return TRUE;    
        } 
		else if(WAIT_OBJECT_0 == dwRes || WAIT_FAILED == dwRes) 
		{
            return FALSE;
        } 
		else 
		{
            return FALSE;
        }
    }
	
	void Sleep(DWORD dwMilliseconds) 
	{
        ::Sleep(dwMilliseconds);
    }
};

#elif defined(_LINUX_)

#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <sys/prctl.h>

#ifndef PR_SET_NAME
#define PR_SET_NAME 15
#endif

typedef int                              BOOL;
typedef unsigned long                    DWORD;
typedef unsigned char                    byte;

#define TRUE                             1
#define FALSE                            0

#define DEFAULT_STACK_SIZE       (200<<10)
#define DEFAULT_THREAD_PRIORITY  100

class CPthreadCtrl
{
	int             m_Flag;
	pthread_mutex_t m_Mutex;
	pthread_cond_t  m_Cond;

public:
	CPthreadCtrl()
	{
		m_Flag = 1;
		pthread_mutex_init(&m_Mutex, NULL);
		pthread_cond_init(&m_Cond, NULL);
	};

	~CPthreadCtrl()
	{
		m_Flag = 0;
		pthread_mutex_destroy(&m_Mutex);
		pthread_cond_destroy(&m_Cond);
	};

public:
	void Suspend()
	{
		pthread_mutex_lock(&m_Mutex);
		m_Flag--;
		pthread_mutex_unlock(&m_Mutex);
	}

	void Resume()
	{
		pthread_mutex_lock(&m_Mutex);
		m_Flag++;
		pthread_cond_signal(&m_Cond);
		pthread_mutex_unlock(&m_Mutex);
	}

	void Wait()
	{
		pthread_mutex_lock(&m_Mutex);
		while(m_Flag <= 0)
		{
			pthread_cond_wait(&m_Cond, &m_Mutex);
		}
		pthread_mutex_unlock(&m_Mutex); 
	}

};

class CThread  //线程类
{
        pthread_t     m_tThread;                            //线程句柄
		byte          m_byThreadPriority;
	    DWORD         m_dwThreadStackSize;
		char*         m_szThreadName;

		CPthreadCtrl m_ThreadCtrl;

        static void* ThreadBody(void* pParam)
        {
			if (!pParam)
				return NULL;
					
			CThread *pThis = (CThread *)pParam ;
			pThis->m_ThreadCtrl.Wait();
			
			if (pThis->m_szThreadName != NULL)
			{
				prctl(PR_SET_NAME, (DWORD)pThis->m_szThreadName);
			}

			pThis ->Run();

			return NULL;
        }

protected:
        virtual DWORD Run() = 0;

        typedef void* (*POSIX_THREAD_ROUTINE) (void* pParam);

public:
        CThread(pthread_t tThread = 0,
			    byte byThreadPriority = DEFAULT_THREAD_PRIORITY,
				DWORD dwThreadStackSize = DEFAULT_STACK_SIZE) 
				:m_tThread(tThread), m_byThreadPriority(byThreadPriority), m_dwThreadStackSize(dwThreadStackSize){};

private:

    // 禁止拷贝构造函数。
    CThread(const CThread&);
    // 禁止赋值操作符。
    void operator=(const CThread&);

public:
        BOOL Start() //创建线程并启动
        {
			if (m_tThread)
				return FALSE;
			
			pthread_attr_t attr;
			if(0 != pthread_attr_init(&attr))
			{
				return FALSE;
			}

			//设定优先级
			sched_param tSchParam;			
			pthread_attr_getschedparam(&attr, &tSchParam);
			tSchParam.sched_priority = m_byThreadPriority;
			pthread_attr_setschedparam(&attr, &tSchParam);

			//设置栈大小
			pthread_attr_setstacksize(&attr, m_dwThreadStackSize);

			//创建线程
			int nRes = pthread_create(&m_tThread,
				                      &attr,
				                      (POSIX_THREAD_ROUTINE)ThreadBody,
				                      (void*)this);
			
			pthread_attr_destroy(&attr);
		
			if(0 != nRes)
			{
				return FALSE;
			}
			
			pthread_detach(m_tThread);
			
			return TRUE;
        }

        void Join() //等待线程退出
        {
            for(;;)
            {
				if(!IsAlive())                      
				{
					return;
				}
				else
				{
					Sleep(10);
				}
			}
        }

		void SuspendThread()
		{
			m_ThreadCtrl.Suspend();
		}
		
		void ResumeThread()
		{
			m_ThreadCtrl.Resume();
		}

        void KillThread()
        {
			if (m_tThread != 0)
			{
				::pthread_cancel(m_tThread);
				m_tThread = 0;
			}
        }

        BOOL IsAlive()
        {
			if (m_tThread == 0) return FALSE;

			int nPolicy;
			struct sched_param tSp;
			int nRes = pthread_getschedparam(m_tThread, &nPolicy, &tSp);
			return (0 == nRes);
		}

        void Sleep(DWORD dwMilliseconds)
        {
			int nS  = dwMilliseconds / 1000;
			int nUs = (dwMilliseconds % 1000) * 1000;
			
			if(nS > 0) 
			{
				sleep(nS);
			}
			
			if(nUs > 0) 
			{
				usleep(nUs);
			}
		}
};

#else

    #error "Not supported OS type"

#endif // #if defined(_LINUX_)



template <class T>
class CXThread :public CThread
{
public:
	CXThread() :CThread(), m_pTheadFuncObj(NULL), m_pmfThreadBody(NULL){};
	virtual ~CXThread(){};

private:  
    // 禁止拷贝构造函数。
    CXThread(const CXThread&);
	// 禁止赋值操作符。
    void operator=(const CXThread&);

private:
	typedef DWORD (T::*ThreadFunc)();
	ThreadFunc m_pmfThreadBody;
	T* m_pTheadFuncObj; 

protected:			
	virtual DWORD Run() //重载线程方法
	{
		if (m_pTheadFuncObj != NULL && m_pmfThreadBody != NULL)
			return (m_pTheadFuncObj->*m_pmfThreadBody)();
		else
			return DWORD(-1);
	} 	
	
public:

    CXThread (T& obj, ThreadFunc threadfunc, int byThreadPriority = DEFAULT_THREAD_PRIORITY, DWORD dwThreadStackSize = DEFAULT_STACK_SIZE)
		     :CThread(0, byThreadPriority, dwThreadStackSize), m_pTheadFuncObj(&obj), m_pmfThreadBody(threadfunc) {}

public:
	BOOL StartThread(T& obj, ThreadFunc pmfThreadfunc)
	{
		m_pTheadFuncObj = &obj;
		m_pmfThreadBody = pmfThreadfunc;

		return CThread::Start();
	}
};

//sample
/*
CXThread<CObj> thread_do;
thread_do.StartThread(*this, &CObj::Do);
*/


#endif // #ifndef _XTHREAD_INCLUDED_
xiaohuh421 2013-09-30
  • 打赏
  • 举报
回复
你的例子我也试过, 只要去掉 _USERENTRY 宏即可. 这个宏类似于 OUT这样的宏, 只是为了标识这个参数的意思, 代替换后是为空的.
baichi4141 2013-09-30
  • 打赏
  • 举报
回复
类的非静态成员函数和静态成员函数的区别,就只在于非静态成员函数隐藏了一个指向对象的指针this
旅客 2013-09-30
  • 打赏
  • 举报
回复
那除了楼上的封装一个线程类以外,还有什么其他方法吗 其实静态的可以,就是不想做什么都要用一个指针指一下,太麻烦了
ri_aje 2013-09-29
  • 打赏
  • 举报
回复
换成这样试试。

_beginthread(Test::mThread, 0, this);
mThread 里再调用 ThreadPROC 干正事儿。
旅客 2013-09-29
  • 打赏
  • 举报
回复
一楼的方法也不行,最后还是要转换,我定义一个union就是为了转换,原因就是不转不行
ri_aje 2013-09-29
  • 打赏
  • 举报
回复
引用 4 楼 sl8023dxf 的回复:
一楼的方法也不行,最后还是要转换,我定义一个union就是为了转换,原因就是不转不行
c++ 中的类成员函数指针与普通函数指针不一样,不能相互转换,无论你使用 union 还是 cast,都没用。 至于你说 #1 的不行,把你修改后的代码发上来,我看一下具体怎么弄的。
ztenv 版主 2013-09-29
  • 打赏
  • 举报
回复
_beginthread比CreateThread要好
xiaohuh421 2013-09-29
  • 打赏
  • 举报
回复
_USERENTRY 实际上就是一个空的宏, 没什么用处. 具体定义可以参考_beginthread参数说明

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧