HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId);
参数
lpThreadAttributes:指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,它被设为NULL,表示使用缺省值。
dwStackSize,线程堆栈大小,一般=0,在任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress,指向线程函数的指针,形式:@函数名,格式不正确将无法调用成功。
线程函数的格式:DWORD WINAPI Threadfnc(LPVOID N); 说明:返回值必须为DWORD,必须使用WINAPI,函数名称Threadfnc可以自己随便命名,函数的参数必须是LPVOID类型。
lpParameter:向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为Nil。
dwCreationFlags :线程标志,可取值如下
CREATE_SUSPENDED 创建一个挂起的线程;
0 创建后立即激活。
lpThreadId:保存新线程的id。线程id是一个全局变量,唯一的表示系统任一进程中的某个线程。但不能根据id获得其handle。
返回值:
函数成功,返回线程句柄;函数失败返回false。
函数说明:
创建一个线程。
一般并不推荐使用 CreateTheard函数,而推荐使用RTL 库里的System单元中定义的 BeginTheard函数,因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。
BOOL CloseHandle(
HANDLE hObject
);
参数
hObject : 代表一个已打开对象handle
返回值
TRUE:执行成功,
FALSE:执行失败,可以调用GetLastError()获知失败原因。
函数说明:
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。
功能: 获取一个结束线程的返回值
BOOL GetExitCodeThread (
HANDLE hThread,
LPDWORD lpExitCode
);
参数:
hThread: 线程对象的句柄
lpExitCode: 用于存储线程的返回值,如果线程结束,那么线程的结束代码会被放在lpExitCode参数中;如果线程尚未结束,lpExitCode的值是STILL_ACTIVE.
返回值:
函数执行成功则返回非0值,否则返回 0(FALSE)。
函数说明:
获取线程结束的返回值。
VOID ExitThread(DWORD dwExitCode);
参数
dwExitCode: 线程的结束代码
返回值
无返回值.
说明
该函数最好用于 C 程序里,在 C++里,return 前会调用析构函数,调用该函数结束线程,并不会调用有关对象的析构函数以及其它的自动清理动作.当在线程里调用该函数后,线程的堆栈将被收回,所有未完成的I/O操作将被取消,于其连接的动态连接库也被分离.
当调用线程的函数返回后,线程自动终止。如果需要在线程的执行过程中终止则可调用该函数。
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
参数
hHandle:事件的句柄,在此指线程句柄;
dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;
此值为0,代表立刻返回
此值为INFINITE,代表无穷等待。
返回值
WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态
WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息
WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态
WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex
函数说明:
设即将等待的线程为线程#1,正在执行的线程为线程#2,调用WaitForSingleObject,设定该函数的第一个参数是线程#2的句柄,则线程#1开始睡眠,直到线程#2结束为止。
创建多个线程,线程并不一定是按照创建的先后顺序结束的。调用该函数只能监测指定的一个线程。
DWORD WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
);
参数
nCount:表示lpHandles所指句柄数据的元素个数,
最大容量是MAXIMUM_WAIT_OBJECTS
lpHandles:指向对象句柄数组的指针
bWaitAll:是否等待所有对象都有信号
此值为false,返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被出发,这个函数返回的只是其中序号最小的那个。
此值为true,
返回值为WAIT_OBJECT_0,表示所有的事件都被设置了 .
返回值为WAIT_ABANDONED_0到(WAIT_ABANDONED_0+ nCount–1) ,表示有一个事件被丢弃
dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果在规定那个时间内有信号状态则返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但事件还是无信号状态则返回WAIT_TIMEOUT;
此值为0,代表立刻返回
此值为INFINITE,代表无穷等待。
返回值
WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态
WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息
WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态
WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex
函数说明:
多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将的不到被出理的机会。
lpHandles数组中不允许有缝隙产生,当某个handle被激发了,你应该在下一次调用WaitForMultipleObjects函数之前将该handle从lpHandles数组中移除。
Windows程序中的标准消息循环看起来想这个样子:
while( GetMessage(&Msg,NULL,0,0) )
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
调用getMessage(),除非有一个消息真正进入消息列队中,否则它不会返回。在此期间,Windows就可以自由的将cpu时间给予其他程序。
常常回到主消息循环是十分重要的事,如果你没有这么做,你的窗口就会停止重绘,就会出现一些用户不喜欢的事情。在你使用WaitForSingleObject或者WaitForMultipleObjects函数时,它在等待某个对象被激发时,你根本没有办法回到主消息循环中去。
为了解决这个问题,主消息循环必须修改,使它可以同时等待消息或者是核心对象被激发,你必须使用MsgWaitForMultipleObjects函数。
DWORD MsgWaitForMultipleObjects (
DWORD nCount,
LPHANDLE pHandles,
BOOL fWaitAll,
DWORD dwMilliseconds,
DWORD dwWakeMask
);
参数
nCount:列表中的句柄数量
pHandles:指向对象句柄数组的指针
fWaitAll:是否等待所有对象都有信号,
dwMilliseconds:等待的最长时间。时间到了如果hHandle没有返回,函数还是要返回的;如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT;
此值为0,代表立刻返回
此值为INFINITE,代表无穷等待。
dwWakeMask :指定哪些消息是观察对象(欲观察的用户输入消息),可以是:
QS_ALLINPUT
QS_HOTKEY
QS_INPUT
QS_KEY
QS_MOUSE
QS_MOUSEBUTTON
QS_MOUSEMOVE
QS_PAINT
QS_POSTMESSAGE
QS_SENDMESSAGE
QS_TIMER
返回值
WAIT_OBJECT_0:函数成功返回,在规定时间内检测到信号状态
WAIT_FAILED:函数失败,可调用GetLastError()查看更多消息
WAIT_TIMEOUT:等待时间到了,还没有检测到信号状态
WAIT_ABANDONED:拥有mutex(互斥器)的线程结束前没有释放mutex
WAIT_TO_COMPLETION:(仅适用于WaitForSingleObjectEx),由于一个I/O完成操作已准备好执行,从而造成了函数的返回。
WAIT_OBJECT_0 + nCount:接受到由dwWakeMask指定的消息
函数说明:
迭代等待指定线程中的特定消息,其实这个函数就是专为等待消息而定义的。
MsgWaitForMultipleObjects函数不允许句柄数组中有缝隙产生,所以当某个句柄被激发了,你应该在下一次调用MsgWaitForMultipleObjects之前先把句柄数组做个整理、压缩
BOOL TerminateThread(
HANDLE hThread,
DWORD dwExitCode
);
参数
hThread:线程的句柄
dwExitCode:线程的结束代码
返回值
True:函数成功
False:函数失败
函数说明:
如果在线程的外面终止线程,则可调用该函数。该函数执行后,线程handle将变成激发状态,并且传回结束代码。
TerminateThread函数是一个危险的函数,应该最不得已的情况下才使用。此函数一旦成功执行,指定的线程会立刻终止执行,那么可能有很多的结束处理工作还没来得及进行,线程的堆栈没有被释放,于是可能会引起内存泄漏- - -,但是此线程加载的DLL也没有机会被通知结束执行。
DWORD SuspendThread(
HANDLE hThread //线程的句柄
);
返回值
函数成功,返回线程的前一个暂停计数或者说是前一个挂起次数,否则返回0x FFFFFFFF
函数说明:
挂起线程。一个线程可以被挂起多次。如果一个线程被挂起n次,则该线程也必须被恢复n次才可能得以执行。。
DWORD ResumeThread(
HANDLE hThread //线程的句柄
);
返回值
函数成功,返回线程目前的挂起次数,否则返回0x FFFFFFFF
函数说明:
唤醒线程。
句柄,是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类对象中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是一个指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows使用了大量的句柄来标识很多对象。
下面创建一个简单的线程例子
#include<iostream> #include<Windows.h> using namespace std; //线程函数 DWORD WINAPI Fun1proc( LPVOID lpparameter//向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL ); //main函数为主线程的入口函数地址 void main() { HANDLE hThread1; hThread1=CreateThread(NULL//第一个参数为NULL,设置为默认的安全性 ,0//第二个参数让新线程与调用线程采用一样的栈大小 ,Fun1proc//第三个参数指定线程1的入口函数地址 ,NULL//第四个参数是传递给线程1的参数 ,0//第五个参数设置为0让线程一旦创建就立即执行 ,NULL//第六个参数新线程的ID ); CloseHandle(hThread1);//关闭新线程的句柄(这里没有终止创建的新线程,只是说主线程对它的引用不感兴趣) cout<<"main thread is running"<<endl; Sleep(5000); //system("pause"); } //线程1的入口函数 DWORD WINAPI Fun1proc( LPVOID lpparameter) { cout<<"thread1 is running!!!"<<endl; return 0; }