创建一个在调用进程的虚拟地址空间内执行的线程。
要创建在另一个进程的虚拟地址空间中运行的线程,请使用 CreateRemoteThread函数。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
指向SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承返回的句柄。如果 lpThreadAttributes
为NULL
,则无法继承句柄。
结构的lpSecurityDescriptor
成员为新线程指定安全描述符。如果lpThreadAttributes
为NULL,则线程获取默认安全描述符。线程的默认安全描述符中的ACL
来自创建者的主要标志。
堆栈的初始大小,以字节为单位。系统将此值四舍五入到最近的页面。如果此参数为零,则新线程使用可执行文件的默认大小。有关更多信息,请参阅线程堆栈大小。
指向由线程执行的应用程序定义函数的指针。该指针表示线程的起始地址。有关线程函数的更多信息,请参见 ThreadProc
指向要传递给线程的变量的指针。
控制线程创建的标志。
值 | 含义 |
---|---|
0 | 该线程在创建后立即运行。 |
CREATE_SUSPENDEDs 0x00000004 | 线程是在挂起状态下创建的,并且在调用ResumeThread函数之前不会运行 。 |
STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000在 | 所述dwStackSize参数指定堆栈的初始保留大小。如果未指定此标志,则dwStackSize指定提交大小。 |
指向接收线程标识符的变量的指针。如果此参数为 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应用商店应用程序支持此功能。
例子
有关示例,请参阅 创建线程。