Windows c++在类中使用多线程

由于当前开发环境为VS2010,暂时不能使用c++11  std 中的thread类,这里只能使用WINapi   CreateThread来创建线程。

一.在类中使用多线程的简单步骤及例子:

1,在类中将线程函数写成静态成员函数(也可以将线程函数做成全局函数)。

2,参数为 (LPVOID pParam)用来传入类 对象指针this,也可以传入其他数据结构。

3,进入调用线程函数的函数时,首先将 类名 *this = (类名*)this;  转化为对象指针。

4,之后用this调用类成员变量和方法就行了。

5,然后使用CreateThread开启线程即可。

方法第三个参数传入该静态函数,CreateThread第四个参数传入对象指针this,最后一个参数可以输出所创建的线程的ID,其他参数可以参考下面的函数介绍

简单示例:

//类头文件  my.h

#include<Windows.h>

class myclass
{
    public:
        static DWORD WINAPI ThreadFun(LPVOID pParam);   线程函数声明

    public:
        void MyTestFun();
        int one;
    
}



//类实现文件  my.cpp
#include "stdafx.h"
#include "my.h"

DWORD WINAPI myclass::ThreadFun(LPVOID pParam)  //线程函数实现
{
   //在线程中要做的事情
   myclass *pObj = (myclass *)pParam;   //传入的参数转化为类对象指针

   int two;

   two=pObj->one;
   return 0;
}

void myclass::MyTestFun()
{
   HANDLE hThread;   //线程句柄
   DWORD  threadId;  //线程ID

   hThread = CreateThread(NULL, 0, ThreadFun, this, 0,&threadId); // 创建线程,this就是本类的对象指针

}





二.CreateThread 函数介绍:

创建一个在调用进程的虚拟地址空间内执行的线程。

要创建在另一个进程的虚拟地址空间中运行的线程,请使用 CreateRemoteThread函数。

语法

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  __drv_aliasesMem LPVOID lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);



参数
lpThreadAttributes
指向SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承返回的句柄。如果 lpThreadAttributes为NULL,则无法继承句柄。

结构的lpSecurityDescriptor成员为新线程指定安全描述符。如果lpThreadAttributes为NULL,则线程获取默认安全描述符。线程的默认安全描述符中的ACL来自创建者的主要标志。

dwStackSize
堆栈的初始大小,以字节为单位。系统将此值四舍五入到最近的页面。如果此参数为零,则新线程使用可执行文件的默认大小。有关更多信息,请参阅线程堆栈大小。

lpStartAddress
指向由线程执行的应用程序定义函数的指针。该指针表示线程的起始地址。有关线程函数的更多信息,请参见 ThreadProc

lpParameter
指向要传递给线程的变量的指针。

dwCreationFlags
控制线程创建的标志。

值    含义
0  :该线程在创建后立即运行。
CREATE_SUSPENDEDs 0x00000004   : 线程是在挂起状态下创建的,并且在调用ResumeThread函数之前不会运行 。
STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000:在所述dwStackSize参数指定堆栈的初始保留大小。如果未指定此标志,则dwStackSize指定提交大小。


lpThreadId
指向接收线程标识符的变量的指针。如果此参数为 NULL,则不返回线程标识符。

返回值
如果函数成功,则返回值是新线程的句柄。

如果函数失败,则返回值为NULL。要获取扩展错误信息,请调用 GetLastError。

请注意,即使lpStartAddress指向数据,代码或无法访问,CreateThread也可能成功 。如果线程运行时起始地址无效,则发生异常,并且线程终止。由于无效的起始地址导致的线程终止被视为线程进程的错误退出。此行为类似于CreateProcess的异步特性,即使它引用无效或缺少动态链接库(DLL),也会创建该进程。

备注
进程可以创建的线程数受可用虚拟内存的限制。默认情况下,每个线程都有一兆字节的堆栈空间。因此,您最多可以创建2,048个线程。如果减小默认堆栈大小,则可以创建更多线程。但是,如果为每个处理器创建一个线程并构建应用程序队列,应用程序维护上下文信息,则应用程序将具有更好的性能。在处理下一个队列中的请求之前,线程将处理队列中的所有请求。

使用THREAD_ALL_ACCESS访问权限创建新的线程句柄。如果在创建线程时未提供安全描述符,则使用创建线程的进程的主令牌为新线程构造默认安全描述符。当调用者尝试使用OpenThread函数访问该线程时,将根据此安全描述符评估调用者的有效令牌以授予或拒绝访问权限。

调用GetCurrentThread 函数时,新创建的线程对自身具有完全访问权限。

Windows Server 2003: 线程对自身的访问权限是通过根据为线程构造的默认安全描述符评估创建线程的进程的主令牌来计算的。如果在远程进程中创建线程,则使用远程进程的主令牌。因此,在调用GetCurrentThread时,新创建的线程可能会减少对自身的访问权限。某些访问权限(包括THREAD_SET_THREAD_TOKEN和THREAD_GET_CONTEXT)可能不存在,从而导致意外故障。因此,建议不要在模仿其他用户时创建线程。

如果线程是在可运行状态下创建的(即,如果未使用CREATE_SUSPENDED标志),则线程可以在CreateThread返回之前开始运行,特别是在调用者接收到创建的线程的句柄和标识符之前。

线程执行从lpStartAddress参数指定的函数开始。如果此函数返回,则DWORD返回值用于在对ExitThread函数的隐式调用中终止线程 。使用 GetExitCodeThread函数获取线程的返回值。

创建的线程的线程优先级为THREAD_PRIORITY_NORMAL。使用 GetThreadPriority和 SetThreadPriority函数来获取和设置线程的优先级值。

当线程终止时,线程对象获得信号状态,满足在对象上等待的任何线程。

线程对象保留在系统中,直到线程终止并且通过调用CloseHandle关闭了它的所有句柄。

ExitProcess, ExitThread, CreateThread, CreateRemoteThread的功能,以及正在启动的处理(如通过一个调用的结果 CreateProcess)的过程中是彼此之间串行化。这些事件中只有一个可以一次发生在地址空间中。这意味着以下限制包含:

在进程启动和DLL初始化例程期间,可以创建新线程,但是在为进程执行DLL初始化之前它们不会开始执行。 
进程中只有一个线程可以一次处于DLL初始化或分离例程中。 
在DLL初始化或分离例程中没有线程之前,ExitProcess不会完成。 
调用C运行时库(CRT)的可执行文件中的线程应使用_beginthreadex和_endthreadex函数进行线程管理,而不是 CreateThread和 ExitThread ; 这需要使用CRT的多线程版本。如果使用CreateThread创建的线程调用CRT,则CRT可以在低内存条件下终止进程。 
Windows Phone 8.1: Windows Phone 8.1及更高版本上的Windows Phone应用商店支持此功能。

Windows 8.1和Windows Server 2012 R2:Windows 8.1,Windows Server 2012 R2及更高版本上的Windows应用商店应用程序支持此功能。
 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值