http://www.buguw.com/?p=187
WIN32线程控制主要实现线程的创建、终止、挂起和恢复等操作,这些操作都依赖于WIN32提供的一组API和具体编译器的C运行时库函数。
1.线程函数
在启动一个线程之前,必须为线程编写一个全局的线程函数,这个线程函数接受一个32位的LPVOID作为参数,返回一个UINT,线程函数的结构为:
- UINT ThreadFunction(LPVOID pParam)
- {
- //线程处理代码
- return0;
- }
复制代码
在线程处理代码部分通常包括一个死循环,该循环中先等待某事情的发生,再处理相关的工作:
- while(1)
- {
- WaitForSingleObject(…,…);//或WaitForMultipleObjects(…)
- //Do something
- }
复制代码
一般来说,C++的类成员函数不能作为线程函数。这是因为在类中定义的成员函数,编译器会给其加上this指针。请看下列程序:
- #include "windows.h"
- #include
- 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
再看下列程序:
- #include "windows.h"
- #include
- 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指针;
我们将上述二个程序改变为:
- #include"windows.h"
- #include
- 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;
- }
复制代码
和
- #include "windows.h"
- #include
- 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)不定义类成员函数为线程函数,而将线程函数定义为类的友元函数。
这样,线程函数也可以有类成员函数同等的权限;
我们将程序修改为:
- #include “windows.h"
- #include
- 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)可以对非静态成员函数实现回调,并访问非静态成员,此法涉及到一些高级技巧,在此不再详述。
-----------------------------------------------------------------------------
linux代码
线程函数定义为类的友元函数
- #include <iostream>
- #include <stdio.h>
- #include <pthread.h>
- #include <errno.h>
- using namespace std;
- class ExampleTask
- {
- public:
- friend void* taskmain(void *param);
- void startTask();
- void done();
- };
- /* 线程函数 */
- void* taskmain(void *param)
- {
- printf("-- %s enter\n", __func__);
- ExampleTask *pTaskMain = (ExampleTask*)param;
- pTaskMain->done();
- printf("-- %s leave\n", __func__);
- }
- void ExampleTask::startTask()
- {
- printf("%s enter\n", __func__);
- pthread_t pthread;
- int ret;
- ret = pthread_create(&pthread, NULL, taskmain, this);
- if ( ret != 0 )
- {
- perror("pthread_create");
- }
- printf("wait for pthread exit\n", __func__);
- pthread_join(pthread, NULL);
- printf("%s leave\n", __func__);
- }
- void ExampleTask::done()
- {
- cout<<"pthread use ExampleTask method!"<<endl;
- }
- int main()
- {
- ExampleTask t;
- t.startTask();
- return 0;
- }
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(235) | 评论(0) | 转发(0) |
0
上一篇:DOS,WINDOWS递归删除指定文件夹或文件
下一篇:EXEC族
相关热门文章
- Qt学习笔记---信号与槽...
- c++防止隐藏的拷贝构造...
- c++ virtual析构函数详解...
- QEMU源码分析系列(三) ...
- 文件系统存在的深层次的原因如...
- Android之开发环境搭建
- Android自定义View的实现...
- AndroidManifest.xml配置文件...
- Android相对布局+圆角按钮+Sha...
- 查看Android应用包名package和...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...