文章目录

  • ​​1.Win32多线程程序设计​​
  • ​​2.CreateThread​​
  • ​​3.GetExitCodeThread​​
  • ​​4.WaitForSingleObject​​
  • ​​5.SuspendThread挂起线程​​
  • ​​6.ResumeThread​​
  • ​​7.CloseHandle​​
  • ​​8.线程终止​​

1.Win32多线程程序设计

  • 使用API线程接口函数:
CreateThread()
ExitThread()
CloseHandle()
  • 使用多线程c runtime library(C运行环境库):
_beginthreadex()
_endthreadex()
其内部调用win32API接口
  • win32API接口与LinuxC 接口对比
CreateThread        pthread_creat
WaitForSingleObject pthread_join
ExitThread pthread_exit
TerminateThread pthread_cancel
GetCurrentThreadId pthread_self

2.CreateThread

包含头文件windows.h
函数原型
HANDLE WINAPI CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
函数返回值:句柄,返回NULL代表线程创建失败
函数参数:
lpThreadAttributes:安全属性指针,NULL表示使用缺省值
dwStackSize:初始堆栈大小,0代表使用默认大小:1MB
lpStartAddress:线程函数,是一个函数指针,可以传一个函数名
lpParameter:线程函数的参数
dwCreationFlags:创建选项,默认为立即执行
lpThreadId:输出参数,表示线程标识符,新线程的ID
  • CreateThread函数的帮助手册

    CreateThread遵循WINAPI调用约定_stdcall,调用约定是标准的调用约定,一些回调函数他的调用约定也是_stdcall。


    C/C++里面默认的调用约定是_cdecl。与_stdcall区别是,eg如果是可变参数,_cdecl表示使用调用者来清除堆栈。

3.GetExitCodeThread

获得指定线程的终止状态
函数原型:
BOOL WINAPI GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);
函数参数:
hThread:由CreateThread()传回的线程句柄
lpExitCode:输出参数,用来接收结束代码
返回值:成功返回TRUE(非0),失败返回FALSE(0)
说明:如果线程尚未终止,lpExitCode的值为STILL_ACTIVE。

4.WaitForSingleObject

等待核心对象(信号量互斥量事件等)处于激发状态或者超时,当线程执行完毕的时候,就处于signaled(激发状态)
函数原型:
DWORD WINAPI WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
返回值:
WAIT_ABANDONED(0x00000080L)
WAIT_OBJECT_0(0x00000000L)
WAIT_TIMEOUT(0x00000102L)
WAIT_FAILED (0xFFFFFFFF)
  • WaitForSingleObject
    F1看到的

5.SuspendThread挂起线程

用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。
函数原型:
DWORD SuspendThread(HANDLE hThread);
函数参数:
hThread:指向要挂起线程的句柄
返回值:
成功返回大于零的数,表示线程之前挂起的计数。失败返回-1,可以使用GetLastError()获得错误信息。
说明:
创建新的线程后,该线程就开始启动执行。但如果在dwCreationFlags中使用了CREATE_SUSPENDED特性,线程并不马上执行,而是先挂起,等到调用ResumeThread后才开始启动线程。
实际上是挂起计数值+1

6.ResumeThread

线程挂起计数减1,当挂起计数为0时,结束线程的挂起状态,执行线程。
函数原型:
DWORD ResumeThread(HANDLE hThread);
函数参数:
hThread:指向要被回复的线程的句柄
返回值:请参考Suspend()函数

7.CloseHandle

函数原型:
BOOL CloseHandle(
HANDLE hObject // handle to object);
功能:将内核对象引用计数减1
上下文指的是线程上下文,使用计数默认=2,暂停计数默认=0(与挂起线程相关,挂起几次,这里是几),
线程执行完毕后,使用计数2-1=1,singnaled=TRUE,调用CloseHandle将使用计数从1-1=0,
此时OS才销毁了这块内存
  • 示例图如下:

8.线程终止

  • 自杀
    线程函数返回(return),线程自动终止
    ExitThread或_endthreadex
ExitThread

在线程内部结束一个线程
函数原型:
VOID ExitThread(DWORD dwExitCode);
函数参数:
dwExitCode:指定此线程的退出代码
返回值:无
  • 他杀
    TerminateThread
TerminateThread

在线程外部强制结束一个线程
函数原型:
BOOL TerminateThread(HANDLE hThread,
DWORD dwExitCode);
函数参数:
hThread:指定需要结束的线程句柄
dwExitCode:指定此线程的退出代码
返回值:成功返回TRUE(非0),失败返回FALSE(0)
  • eg:01.cpp
#include <windows.h>
#include <iostream>
using namespace std;

//WINAPI就是_stdcall
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
//GetCurrentThreadId类似于LinuxC中的pthread_self
cout<<"GetCurrentThreadId()="<<GetCurrentThreadId()<<endl;//返回本线程ID
int n = (int)lpParameter;//强转为int
while (n--)
{
cout<<"this is a test"<<endl;
Sleep(1000);//毫秒为单位,1000=1s
}
return 100;
}


int main()
{

DWORD dwThreadId;
//类似于LinuxC下的pthread_creat
//LPVOIDs是void*,typedef void *LPVOID
//typedef unsignd long DWORD,typedef DWORD *LPDWORD,typedef void *HANDLE
//CreateThread(默认的安全属性,线程堆栈大小默认1M,线程的入口函数,线程函数的参数,,返回线程ID)
//HANDLE标识了一个线程,该句柄会索引OS为该线程开辟的内存而已。类似Linux打开文件返回的fd
//(LPVOID)5强转为指针类型
//CREATE_SUSPENDED表示线程被挂起,不会被执行
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)5, CREATE_SUSPENDED/*0*/, &dwThreadId);
if (hThread == NULL)
{
//网络错误使用WSAGetLastError(),其余错误用GetLastError
cout<<"error with code"<<GetLastError()<<endl;
exit(1);
}

cout<<"dwThreadId="<<dwThreadId<<endl;//与GetCurrentThreadId一样

SuspendThread(hThread);//挂起线程
ResumeThread(hThread);//恢复挂起线程去执行
ResumeThread(hThread);//因为挂起了2次,所以要恢复2次

//方法1
//DWORD exitCode = 0;
主线程轮询子线程是否退出
//do
//{
// GetExitCodeThread(hThread, &exitCode); // 这个函数不会阻塞,因而处于忙等待,但是我们应当尽可能避免。
//} while (exitCode == STILL_ACTIVE);

//cout<<"exitCode="<<exitCode<<endl;//线程的退出码,这里是100

//CloseHandle(hThread);//在这里CloseHandle,子线程并未销毁,WaitForSingleObject不能用了而已

//方法2
DWORD ret;
//(线程句柄,线程超时时间)
//INFINITE表示永久等待
//类似于LinuxC下的pthread_join
ret = WaitForSingleObject(hThread, INFINITE);//WaitForSingleObject会阻塞,所以不会忙等
if (ret == WAIT_FAILED)
{
cout<<"error with code="<<GetLastError()<<endl;
exit(1);
}
else if (ret == WAIT_OBJECT_0)
{
cout<<"wait succ"<<endl;
}

//Sleep(10*1000);

CloseHandle(hThread);
return 0;
}
  • 测试:

(P101)多线程二:Win32多线程程序设计等_函数参数


(P101)多线程二:Win32多线程程序设计等_句柄_02

(P101)多线程二:Win32多线程程序设计等_句柄_03