试验过程中调用了不少系统函数,并且涉及到一些系统级的概念,在此记录下来做为解决问题的一种方式。也许在以后的编程的过程中是否可以通过调用系统平台上的东西来完成一些任务,这仍不失为一种好的思维方式。
多线程编程时通常要考虑到进程是否已经结束,进程等待等问题。那么你需要这两个函数(WaitForSingleObject,WaitForMultipleObjects)来帮助你判断是否进程已经结束,接下来的两个小时,我们来做一下关于这两个函数的试验。体验一下内核状态下的这些东西。
#include<iostream> #include<Windows.h> using namespace std; DWORD WINAPI cProc(LPVOID lpParameter){ for (int i = 0; i < 5; i++){ cout << i << endl; } return 0; } int main(){ HANDLE hThread = CreateThread(0, 0, cProc, 0, 0, 0); DWORD ret = WaitForSingleObject(hThread, 1); if (ret == WAIT_OBJECT_0){ cout << "线程执行结束!" << endl; } else if (ret == WAIT_TIMEOUT){ cout << "线程没能在指定时间内运行完!" << endl; } else{ cout << "对象有信号但是还不能执行!" << endl; } CloseHandle(hThread); return 0; }
waitForSingleObject这个函数的返回类型为DWORD,它有三个值:
WAIT_OBJECT_0, 表示等待的对象有信号(对线程来说,表示执行结束);
WAIT_TIMEOUT, 表示等待指定时间内,对象一直没有信号(线程没执行完);
WAIT_ABANDONED 表示对象有信号,但还是不能执行 一般是因为未获取到锁或其他原因
这个函数的参数就没有什么好解释的了,第一个参数就是你要判断的对象的句柄,第二个参数就是等待的时间大小,这里我设置为1ms,当我把进程函数体中的循环遍数调大一下就会出现WAIT_TIMEOUT这个返回值。这个不是固定的。不同情况下,不同电脑也不同。
waitForMultipleObjects
这个函数是用来等待多个内核对象的它的函数原型为:
DWORD WINAPI WaitForMultipleObjects( _In_ DWORD nCount, _In_ const HANDLE *lpHandles, _In_ BOOL bWaitAll, _In_ DWORD dwMilliseconds );nCount这个参数是指定被等待的对象的数目。This parameter cannot be zero.lpHandles 这个参数还是比较好玩的,它是被等待对象的数组的地址,且这个数组里的对象可以是不同类型,这个不同类型是说都是HANDLE类型,但是可以指代不同的含义,例如lpHandles[0]一个线程的句柄,lpHandles[1]是一个互斥信号量的句柄,这都是允许的。bWaitAll这个参数为ture时,这个函数等待所有被等待对象被激活(我觉得激活这个词不太好,原句:If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled.)当为false时,只要这个数组中等待的对象中有一个被signaled,就立即返回,然后返回值是WAIT_OBJECT_0+(被signaled的对象在数组中的下标)。
这个函数的返回值,我就不多说了,我觉得翻译不好,还是在使用过程中结合WaitForMultipleObjects 来理解吧。
#include<iostream> #include<Windows.h> using namespace std; DWORD WINAPI cProc(LPVOID lpParameter){ for (int i = 0; i < 5; i++){ cout << i << endl; } return 0; } int main(){ HANDLE hThread[2]; hThread[0] = CreateThread(0, 0, cProc, 0, 0, 0); hThread[1] = CreateThread(0, 0, cProc, 0, 0, 0); DWORD dwRet = WaitForMultipleObjects(2, hThread, true, INFINITE); cout << dwRet - WAIT_OBJECT_0 << "执行完毕!" << endl; return 0; }
这个函数的执行时没有问题的。
但是如果把WaitForMultipleObjects中的参数改为false,就会出现如下现象:
为什么这个1的输出会不跟“执行完毕!”在同一行呢。这其实就是一个waitForSingleObjects当其接收到一个线程结束后,另一个线程这个时候就和主线程并发执行,这个时候主线程输出了1还没有等待要输出执行完毕呢线程被阻塞,然后子线程获得处理机就会出现这种状况,下面这个更明显,都输出了执行完毕了,另一个线程还在输出。