创建线程函数的方法

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)可以对非静态成员函数实现回调,并访问非静态成员,此法涉及到一些高级技巧,在此不再详述。

时间: 2024-08-01 01:04:59

创建线程函数的方法的相关文章

[笔记]linux下和windows下的 创建线程函数

linux下和windows下的 创建线程函数 1 #ifdef __GNUC__ 2 //Linux 3 #include <pthread.h> 4 #define CreateThreadEx(tid,threadFun,args) pthread_create(tid, 0, threadFun, args) 5 #define CloseHandle(ph) 6 7 int pthread_create( 8 //指向线程标识符的指针. 9 pthread_t *restrict t

驱动开发之 创建线程函数PsCreateSystemThread

PsCreateSystemThread 创建一个执行在内核模式的系统线程. 注意:创建线程必须用函数PsTerminateSystemThread强制线程结束.否则该线程是无法自动退出的. 函数原型: [cpp] view plain copy print? NTSTATUS PsCreateSystemThread( _Out_      PHANDLE ThreadHandle, _In_       ULONG DesiredAccess, _In_opt_   POBJECT_ATTR

java创建线程两种方法

/* 进程:是一个正在执行中的程序 每一个进程执行都有执行顺序,该顺序是一个执行路径,或叫控制单元 线程:就是进程中一个独立的控制单元 线程在控制着进程的执行 一个进程至少包含一个线程 Java VM 启动时会有个进程java.exe 该进程中至少有一个线程复制java程序的执行,这个线程运行的代码存在于main方法中, 该线程称之为主线程 JVM启动不止一个线程,还有复制垃圾回收机制的线程 创建线程:(1)继承Thread类;复写run方法;创建对象,调用start方法 (2)实现Runnab

【Simple Java】Java中怎样创建线程安全的方法

面试问题: 下面的方法是否线程安全?怎样让它成为线程安全的方法? class MyCounter { private static int counter = 0; public static int getCount() { return counter++; } } 本篇文章将解释一个常见的面试题,该问题被谷歌和很多其它公司问起过.它涉及的相对比较初级,而不是关于怎样去设计复杂的并发程序. 首先,这个问题的答案是No,因为counter++操作不是一个原子操作,而是由多个原子操作组成. 举个

如何创建线程详解(二)

1.在 Windows 操作系统中创建进程 在 windows 操作系统中,我们创建一个进程通常就是打开某个应用软件,这便在电脑中创建了一个进程.更原始一点的,我们在命令提示符中来做(我们以打开记事本这个进程为例): 第一步:windows+R,输入cmd,打开 cmd 命令提示符 第二步:在命令提示符中输入 notepad,按 Enter 键便会弹出记事本应用软件    PS:常用的windows 应用软件命令 1.regedit:打开注册表编辑器 2.control:打开控制面板 3.msc

linux线程笔记1之创建线程

1 线程与进程的对比 这里有一个笔记详细的阐述 http://blog.csdn.net/laviolette/article/details/51506953 2 创建线程函数 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,                          void *(*start_routine) (void *), void *arg); 参数意义: typedef unsigned l

【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?

前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); //此处不该利用Executors工具类来初始化线程池 但是,在<阿里巴巴Java开发手册>中有一条 [强制]线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方

高并发之——从源码角度分析创建线程池究竟有哪些方式

前言 在Java的高并发领域,线程池一直是一个绕不开的话题.有些童鞋一直在使用线程池,但是,对于如何创建线程池仅仅停留在使用Executors工具类的方式,那么,创建线程池究竟存在哪几种方式呢?就让我们一起从创建线程池的源码来深入分析究竟有哪些方式可以创建线程池. 使用Executors工具类创建线程池 在创建线程池时,初学者用的最多的就是Executors 这个工具类,而使用这个工具类创建线程池时非常简单的,不需要关注太多的线程池细节,只需要传入必要的参数即可.Executors 工具类提供了

.NET中创建线程的方法

1:UI线程.这个线程是操作系统自动创建的,你画了个winform,那么程序一启动,自然有了这么个线程.值得注意的是,你添加一个Timer控件,现实的多线程,实际上,依然在UI线程里.只是定时被Timer夺去控制权而已,本质上依然是单线程.另一个线索也可以论证:本来非UI线程想更新UI界面,是需要利用delegate,involk等来实现的,但是在timer控件的线程里,是不需要的.2:Thread thread = new Thread(obj.functionName); thread.st