您的位置:首页 > 其它

用类的非静态成员函数作为线程入口函数的方法--转

2013-10-24 17:00 190 查看

 

一个类里的函数,通常要作为线程的入口函数,必须把它指定为static类型。

static类型的类成员函数,并不具有this指针,也不能访问到protected或private类型的类成员。

因为以上的不便,我们会想,怎样把一个普通的类成员函数,当作线程的“入口函数”呢?

方法还是有的,具体说来:

1. 创建一个线程,将类指针this和“入口函数”当作参数传入, 其实这里的“入口函数”已经不是线程真正的入口函数了.

2. 利用->*操作符, 调用该“入口函数”, (this->*入口函数) (arg)

得益于c++的强大模版, 下面是该过程的一个封装, 使用也很简单:

相对于pthread的 pthread_create (thread_id, attr, entry, arg),

如果要把类成员函数当作线程入口, 只需要多加一个this,

thread_proxy(this, thread_id, attr, entry, arg)

/////////////////////////////////////////////////////

//代码

#include <cstdio>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>

template <class T>

class thread_proxy_imp

{

protected:

typedef struct

{

T *obj;

void (T::*start_routine)(void *);

void *arg;

sem_t sem;

} thread_param;

    static void *thread_proxy_entry (void *arg)

{

thread_param *param_ptr = static_cast<thread_param *> (arg);

thread_param param = *param_ptr;

sem_post (¶m_ptr->sem);

        /* 注意 ->* 操作符 */

(param.obj->*param.start_routine) (param.arg);

}

public:

int pthread_create (

T *obj,

pthread_t *thread,

const pthread_attr_t *attr,

void (T::*start_routine)(void *),

void *arg)

{

int rt;

thread_param param = {obj, start_routine, arg};

/* 为防止param在新线程使用它之前被析构,加上一个semaphore. */

sem_init (¶m.sem, 0, 0);

rt = ::pthread_create (thread, attr, &thread_proxy_imp::thread_proxy_entry, static_cast<void *> (¶m));

sem_wait (¶m.sem);

sem_destroy (¶m.sem);

return rt;

}

};

te
ca63
mplate <class T>

int thread_proxy (

T *obj,

pthread_t *thread,

const pthread_attr_t *attr,

void (T::*start_routine)(void *),

void *arg)  

{

return thread_proxy_imp<T> ().pthread_create (obj, thread, attr, start_routine, arg);

}

class C

{

public:

pthread_t m_thread;

int create_thread ()

{

thread_proxy(this, &m_thread, NULL, &C::thread_entry, (void *) 56);           

}

protected:

void thread_entry (void *arg)

{

for (int i = 0; i < 10; i++)

{

printf ("arg: %d\n", arg);

sleep (1);

}

};

};

int main ()

{

C c;

c.create_thread ();

pthread_join (c.m_thread, NULL);

printf ("exit ...\n");

return 0;

}

===================================================================================

[问题提出]

如何用非静态的类成员函数,作为线程函数!

[问题解答]

可以使用它的隐藏参数,作为线程函数的参数,这样就可匹配参数!

[程序实现]

#include <windows.h>

#include <conio.h>

#include <stdio.h>

class t

{

public:

void Run();

t();

protected:

char c[256];

DWORD WINAPI ThreadFunc();

};

typedef DWORD (WINAPI   t::* pThreadFunc)();

t::t()

{

strcpy(c, "Welcome to use thread proc");

}

DWORD WINAPI t::ThreadFunc()

{

MessageBox(NULL, c, "xixi", MB_OK);

return 0;

}

typedef DWORD (WINAPI * PTHREADFUNC)(LPVOID);

void t::Run()

{

pThreadFunc p = ThreadFunc;

DWORD dwAddress;

memcpy(&dwAddress,&p,sizeof(p));

PTHREADFUNC p1;

memcpy(&p1, &dwAddress, sizeof(p1));

DWORD dwTID;

HANDLE hf;

hf = CreateThread(NULL, 0, p1, this, 0, &dwTID);

if (hf){

CloseHandle(hf);

}

}

void main()

{

t t1;

t1.Run();

getch();

}

==================================================================================

使用就太简单了:任何含有线程成员函数的类,之需要做成这个类的派生类,

然后就可以随时使用 StartThread(TMethod fMethod, TParam& rParam) 函

数,第一个参数是要运行的成员函数,第二个参数是欲调用该成员函数的参

数。呵呵,连 this 都不用传了!

参数这里以后还要继续改进,使得对无参数等情况支持得更好,过两天有空

再帖吧。

#include "stdafx.h"

#include <windows.h>

#include <process.h>

#include <iostream>

using namespace std;

class ClassWithThreadMethod {

public:

template <class TMethod, class TParam> class CThreadMethod {

public:

typedef int(__stdcall ClassWithThreadMethod::*IMethod)(TParam);

uintptr_t StartThread(ClassWithThreadMethod* pObj, TMethod fMethod,

TParam& rParam) {

uintptr_t hThread = 0;

if (pObj && fMethod) {

pObject = pObj, fIMethod = (IMethod)fMethod, oParam = rParam;

hThWait = CreateEvent(NULL, TRUE, FALSE, NULL);

hThread = _beginthreadex(NULL, 0, ThreadFunc, this, 0, &hThread);

CloseHandle((WaitForSingleObject(hThWait ,INFINITE), hThWait));

}

return hThread;

}

private:

static unsigned __stdcall ThreadFunc(void* pThreadMethod) {

CThreadMethod TMCopy = *((CThreadMethod*)pThreadMethod);

#include <iostream>

using namespace std;

class ClassWithThreadMethod {

public:

template <class TMethod, class TParam> class CThreadMethod {

public:

typedef int(__stdcall ClassWithThreadMethod::*IMethod)(TParam);

uintptr_t StartThread(ClassWithThreadMethod* pObj, TMethod fMethod,

TParam& rParam) {

uintptr_t hThread = 0;

if (pObj && fMethod) {

pObject = pObj, fIMethod = (IMethod)fMethod, oParam = rParam;

hThWait = CreateEvent(NULL, TRUE, FALSE, NULL);

hThread = _beginthreadex(NULL, 0, ThreadFunc, this, 0, &hThread);

CloseHandle((WaitForSingleObject(hThWait ,INFINITE), hThWait));

}

return hThread;

}

private:

static unsigned __stdcall ThreadFunc(void* pThreadMethod) {

CThreadMethod TMCopy = *((CThreadMethod*)pThreadMethod);

SetEvent(((CThreadMethod*)pThreadMethod)->hThWait);

return (TMCopy.pObject->*TMCopy.fIMethod)(TMCopy.oParam);

}

IMethod fIMethod;

TParam   oParam;

HANDLE   hThWait;

ClassWithThreadMethod* pObject;

};

template <class TMethod, class TParam>

HANDLE StartThread(TMethod fMethod, TParam& rParam)

{

CThreadMethod<TMethod, TParam> oTMethod;

return (HANDLE)oTMethod.StartThread(this, fMethod, rParam);

}

};

int g_nGlobal=0;

class CMyThread : public ClassWithThreadMethod

{

public:

CMyThread() : m_nNumber(0) { }

struct DualParam {

int nParam1;

int nParam2;

} oParam;

int __stdcall MyThreadMethod(int nParam1, int nParam2)

{

m_nNumber = nParam1 * 1000 + nParam2 + 1;

g_nGlobal = nParam2 * 1000 + nParam1 + 1;

return 0;

}

void TestThreadMethod() {

oParam.nParam1 = 3;

oParam.nParam2 = 9;

HANDLE hThread = StartThread(MyThreadMethod, oParam);

CloseHandle((WaitForSingleObject(hThread,INFINITE), hThread));

}

int m_nNumber;

};

CMyThread MyThread;

int main(int argc, char* argv[])

{

MyThread.TestThreadMethod();

cout << g_nGlobal << " " << MyThread.m_nNumber << endl;

return 0;

}

转自:http://hi.baidu.com/%B8%DF%C9%BD%C1%F7%CB%AE/blog/item/6fa91a4c27c584ffd62afc46.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 线程函数