概述
Win32提供了一些列的API函数来完成线程的创建、挂起、恢复、终结以及通信等共工作。
多线程需要包含头文件#include <Windows.h>。
CWinThread类
-
MFC的多线程启动使用的是:AfxBeginThread(),是对CWinThread的一层外包装。直接使用CWinThread会获得更好的控制,还可以储存“线程间通讯”数据。
-
CWinThread封装了对线程的操作,代表在应用程序中一个线程的执行。
CWinThread::SuspendThread —— 将已经激活的线程挂起。
CWinThread::ResumeThread —— 将挂起的线程重新激活
CWinThread::SetThreadPriority —— 设置线程的优先级
CWinThread::GetMainWnd —— 获取用户界面线程中的主界面地址
CWinThread::InitInstance —— 初始化用户界面线程中资源,创建用户界面线程是必须重载。
CWinThread::ExitInstance —— 释放用户界面线程中资源,创建用户界面线程是必须重载。 -
常见的启动线程函数有三个:
CreateThread(), _beginThread(以及_beginThreadEx()),AfxBeginThread() 前两个是sdk函数,第三个是mfc函数
CreateThread详解
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,则线程获取默认安全描述符。 - dwStackSize
线程堆栈的初始大小,以字节为单位。如果此参数为零,则新线程使用可执行文件的默认大小。默认大小即采用与调用该函数的线程相同的栈空间大小。 - lpStartAddress
指向由线程执行的应用程序定义函数的指针。该指针表示线程的起始地址。其实起始地址就是函数的名字。 - lpParameter
要传递给新建线程的命令行参数。 - dwCreationFlags
控制线程创建的标志。 - lpThreadId
指向新建线程的ID号。如果此参数为 NULL,则不返回线程标识符。
值 | 含义 |
---|---|
0 | 该线程在创建后立即运行 |
CREATE_SUSPENDED 0x00000004 | 线程是在挂起状态下创建的,并且在调用ResumeThread函数之前不会运行 。 |
STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 | 所述dwStackSize参数指定堆栈的初始保留大小。如果未指定此标志,则dwStackSize指定提交大小。 |
注意
线程ID和线程句柄的关系:
句柄是用户实现对线程操作的桥梁,线程ID是线程在系统中的唯一标识。如果两个线程返回的ID相同,这说明两个线程是同一个线程。将线程ID设置为NULL,表示我们对线程的ID不感兴趣,即不利用线程的ID进行一定的操作。
线程的句柄并不是线程的唯一标识,现成的句柄只是用来访问该线程的一个32位值。尽管相同的句柄一定表示同一线程,但是同一线程可能拥有两个打开的句柄。因此不能用句柄来区分两个线程是否是同一线程。
线程ID的作用:向一个线程投递消息。
线程句柄:基本上,所有操作线程的WindowsAPI均使用句柄。
没多一个句柄,线程对象就多一个引用计数,当引用计数为0时,线程对象将被系统回收利用,一个线程对象可以有很多个句柄指向它。
我们经常看到这样的代码:
HANDLE hThrd = CreateThread( NULL, 0