成员函数做为线程函数
2013-10-23 10:29
239 查看
WIN32线程控制主要实现线程的创建、终止、挂起和恢复等操作,这些操作都依赖于WIN32提供的一组API和具体编译器的C运行时库函数。
1.线程函数
在启动一个线程之前,必须为线程编写一个全局的线程函数,这个线程函数接受一个32位的LPVOID作为参数,返回一个UINT,线程函数的结构为:
[cpp] view
plaincopy
UINT ThreadFunction(LPVOID pParam)
{
//线程处理代码
return0;
}
在线程处理代码部分通常包括一个死循环,该循环中先等待某事情的发生,再处理相关的工作:
[cpp] view
plaincopy
while(1)
{
WaitForSingleObject(…,…);//或WaitForMultipleObjects(…)
//Do something
}
一般来说,C++的类成员函数不能作为线程函数。这是因为在类中定义的成员函数,编译器会给其加上this指针。请看下列程序:
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void taskmain(LPVOID param);
void StartTask();
};
void ExampleTask::taskmain(LPVOID param)
{}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,NULL);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
程序编译时出现如下错误:
error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
None of the functions with this name in scope match the target type
再看下列程序:
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void taskmain(LPVOID param);
};
void ExampleTask::taskmain(LPVOID param)
{}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
_beginthread(ExampleTask::taskmain,0,NULL);
return 0;
}
程序编译时会出错:
error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
None of the functions with this name in scope match the target type
如果一定要以类成员函数作为线程函数,通常有如下解决方案:
(1)将该成员函数声明为static类型,去掉this指针;
我们将上述二个程序改变为:
[cpp] view
plaincopy
#include"windows.h"
#include<process.h>
class ExampleTask
{
public:
void static taskmain(LPVOID param);
void StartTask();
};
void ExampleTask::taskmain(LPVOID param)
{}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,NULL);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
和
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void static taskmain(LPVOID param);
};
void ExampleTask::taskmain(LPVOID param)
{}
int main(int argc, char* argv[])
{
_beginthread(ExampleTask::taskmain,0,NULL);
return 0;
}
均编译通过。
将成员函数声明为静态虽然可以解决作为线程函数的问题,但是它带来了新的问题,那就是static成员函数只能访问static成员。解决此问题的一种途径是可以在调用类静态成员函数(线程函数)时将this指针作为参数传入,并在改线程函数中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。
(2)不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。
这样,线程函数也可以有类成员函数同等的权限;
我们将程序修改为:
[cpp] view
plaincopy
#include “windows.h"
#include <process.h>
class ExampleTask
{
public:
friend void taskmain(LPVOID param);
void StartTask();
};
void taskmain(LPVOID param)
{
ExampleTask * pTaskMain = (ExampleTask *) param;
//通过pTaskMain指针引用
}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,this);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
(3)可以对非静态成员函数实现回调,并访问非静态成员,此法涉及到一些高级技巧,在此不再详述。
1.线程函数
在启动一个线程之前,必须为线程编写一个全局的线程函数,这个线程函数接受一个32位的LPVOID作为参数,返回一个UINT,线程函数的结构为:
[cpp] view
plaincopy
UINT ThreadFunction(LPVOID pParam)
{
//线程处理代码
return0;
}
在线程处理代码部分通常包括一个死循环,该循环中先等待某事情的发生,再处理相关的工作:
[cpp] view
plaincopy
while(1)
{
WaitForSingleObject(…,…);//或WaitForMultipleObjects(…)
//Do something
}
一般来说,C++的类成员函数不能作为线程函数。这是因为在类中定义的成员函数,编译器会给其加上this指针。请看下列程序:
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void taskmain(LPVOID param);
void StartTask();
};
void ExampleTask::taskmain(LPVOID param)
{}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,NULL);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
程序编译时出现如下错误:
error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
None of the functions with this name in scope match the target type
再看下列程序:
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void taskmain(LPVOID param);
};
void ExampleTask::taskmain(LPVOID param)
{}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
_beginthread(ExampleTask::taskmain,0,NULL);
return 0;
}
程序编译时会出错:
error C2664: '_beginthread' : cannot convert parameter 1 from 'void (void *)' to 'void (__cdecl *)(void *)'
None of the functions with this name in scope match the target type
如果一定要以类成员函数作为线程函数,通常有如下解决方案:
(1)将该成员函数声明为static类型,去掉this指针;
我们将上述二个程序改变为:
[cpp] view
plaincopy
#include"windows.h"
#include<process.h>
class ExampleTask
{
public:
void static taskmain(LPVOID param);
void StartTask();
};
void ExampleTask::taskmain(LPVOID param)
{}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,NULL);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
和
[cpp] view
plaincopy
#include "windows.h"
#include <process.h>
class ExampleTask
{
public:
void static taskmain(LPVOID param);
};
void ExampleTask::taskmain(LPVOID param)
{}
int main(int argc, char* argv[])
{
_beginthread(ExampleTask::taskmain,0,NULL);
return 0;
}
均编译通过。
将成员函数声明为静态虽然可以解决作为线程函数的问题,但是它带来了新的问题,那就是static成员函数只能访问static成员。解决此问题的一种途径是可以在调用类静态成员函数(线程函数)时将this指针作为参数传入,并在改线程函数中用强制类型转换将this转换成指向该类的指针,通过该指针访问非静态成员。
(2)不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。
这样,线程函数也可以有类成员函数同等的权限;
我们将程序修改为:
[cpp] view
plaincopy
#include “windows.h"
#include <process.h>
class ExampleTask
{
public:
friend void taskmain(LPVOID param);
void StartTask();
};
void taskmain(LPVOID param)
{
ExampleTask * pTaskMain = (ExampleTask *) param;
//通过pTaskMain指针引用
}
void ExampleTask::StartTask()
{
_beginthread(taskmain,0,this);
}
int main(int argc, char* argv[])
{
ExampleTask realTimeTask;
realTimeTask.StartTask();
return 0;
}
(3)可以对非静态成员函数实现回调,并访问非静态成员,此法涉及到一些高级技巧,在此不再详述。
相关文章推荐
- 成员函数做为线程函数
- 成员函数做为线程函数
- 成员函数做为线程函数
- 类的成员函数做为线程函数【转载】
- 成员函数线程适配器
- 类成员函数创建线程
- 把类成员函数封装成线程API所需要的函数
- 如何实现类的成员函数创建线程
- 不使用汇编在vc中转换类的成员函数为一个线程的通用代码
- [系统级] 线程入口函数作为类成员
- VC6中,为什么只有类中的static成员函数,才可以做为线程启动函数(ThreadProc)?
- 如何实现利用类成员函数创建线程
- 在类中使用类成员函数创建线程
- 类成员函数作为线程函数使用
- linux C++ 类成员函数中创建线程,且能访问类中其他成员变量
- 线程函数如何共享类成员
- 在单独线程中执行对象成员函数
- MFC 中一个界面开启的线程函数如何访问另一个界面的成员
- linux C++ 类成员函数中创建线程,且能访问类中其他成员变量
- 将类成员函数作为线程入口函数——关于C++ 类静态成员的学习