学习笔记 -- Win32多线程程序设计(二) WaitForSingleObject and WaitForMultipleObjects

通过前一篇文章,我们已经知道可以通过GetExitCodeThread 来不断获取线程状态确定线程是否已经结束。
这种方法叫做busy loop或者busy wait。但是这种方法并不好,因为它会浪费CPU 可用时间。
只有一两个线程这样去等待还可以,但是如果有成千上百个线程这样去等待的话,CPU的资源将被等待占用,而实际工作的CPU资源将所剩无几。


所以我们需要另外一种等待方式
DWORD WINAPI WaitForSingleObject(
  _In_ HANDLE hHandle,
  _In_ DWORD  dwMilliseconds
);
具体参考MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx


WaitForSingleObject 不仅可以等待线程,还可以等待文件I/O操作,互斥器(Mutexes)等等。

#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;


DWORD WINAPI ThreadFunc(LPVOID);

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hThread1 = NULL;
	HANDLE hThread2 = NULL;
	DWORD dwThreadId1 = 0;
	DWORD dwThreadId2 = 0;
	//DWORD dwExitCode1 = 0;
	//DWORD dwExitCode2 = 0;

	hThread1 = CreateThread(0,0,ThreadFunc,(LPVOID)1,0,&dwThreadId1);
	if (hThread1)
	{
		cout<<"Thread1 started"<<endl;
	}

	hThread2 = CreateThread(0,0,ThreadFunc,(LPVOID)2,0,&dwThreadId2);
	if (hThread2)
	{
		cout<<"Thread2 started"<<endl;
	}

	WaitForSingleObject(hThread1,INFINITE);
	cout<<"Thread1 is over"<<endl;

	WaitForSingleObject(hThread2,INFINITE);
	cout<<"Thread2 is over"<<endl;

	//for (;;)
	//{
	//	cout<<"Press any key to exit"<<endl;
	//	getchar();

	//	GetExitCodeThread(hThread1,&dwExitCode1);
	//	GetExitCodeThread(hThread2,&dwExitCode2);

	//	if (dwExitCode1 == STILL_ACTIVE)
	//	{
	//		cout<<"Thread1 is working"<<endl;
	//	}
	//	if (dwExitCode2 == STILL_ACTIVE)
	//	{
	//		cout<<"Thread2 is working"<<endl;
	//	}
	//	if (dwExitCode1 != STILL_ACTIVE
	//		&& dwExitCode2 != STILL_ACTIVE)
	//	{
	//		cout<<"All threads finished"<<endl;
	//		break;
	//	}
	//}

	if (hThread1)
	{
		CloseHandle(hThread1);
	}

	if (hThread2)
	{
		CloseHandle(hThread2);
	}

	//cout<<"Thread1 exit with "<<dwExitCode1<<endl;
	//cout<<"Thread2 exit with "<<dwExitCode2<<endl;

	system("PAUSE");

	return 0;
}

DWORD WINAPI ThreadFunc(LPVOID n)
{
	int j = (int)n;
	for (int i=0;i<10;i++)
	{
		Sleep(j*1000);
		cout<<j<<endl;

		if (j == 1 && i == 1)
		{
			ExitThread(4);
		}
	}

	return 0;
}

同时等待多个线程结束可以使用WaitForMultipleObjects
DWORD WINAPI WaitForMultipleObjects(
  _In_       DWORD  nCount,
  _In_ const HANDLE *lpHandles,
  _In_       BOOL   bWaitAll,
  _In_       DWORD  dwMilliseconds
);
具体参考MSDN: https://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx
该API 返回值比较复杂(以下说明来自《Win32 多线程程序设计》)
1. 如果因时间终了而返回,则返回值是WAIT_TIMEOUT, 类似WaitForSingleObject()。
2. 如果bWaitAll是TRUE, 那么返回值将是WAIT_OBJECT_0。
3. 如果bWaitAll是FALSE, 那么将返回值减去WAIT_OBJECT_0,就是表示数组中的哪一个handle被激发了。(激发就是线程结束了)
4. 如果你等待的对象中有任何mutexes, 那么返回值可能从WAIT_ABANDONED_0 到 WAIT_ABANDONED_0 + nCount - 1。
5. 如果函数失败,它会传回WAIT_FAILED. 这时候你可以使用GetLastError() 找出失败的原因。


#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;

#define THREAD_POOL_SIZE	3
#define HANDLE_MAX_INDEX	THREAD_POOL_SIZE - 1
#define MAX_TASK_NUMBER		6


DWORD WINAPI ThreadFunc(LPVOID);

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hThread[THREAD_POOL_SIZE];
	DWORD dwThreadId = 0;
	int iIndex = 0;
	
	for (int i=1; i<= MAX_TASK_NUMBER; i++)
	{
		if (i>THREAD_POOL_SIZE)
		{
			DWORD dwRet = WaitForMultipleObjects(THREAD_POOL_SIZE,
												hThread,
												FALSE,
												INFINITE);
			iIndex = dwRet - WAIT_OBJECT_0;
			cout<<"Thread "<<iIndex+1<<" is end."<<endl;
			CloseHandle(hThread[iIndex]);
		}

		hThread[iIndex++] = CreateThread(0,0,ThreadFunc,(LPVOID)iIndex,0,&dwThreadId);
		cout<<"Thread "<<iIndex<<" started"<<endl;
	}

	WaitForMultipleObjects(THREAD_POOL_SIZE,
							hThread,
							TRUE,
							INFINITE);

	for (int i=0;i<THREAD_POOL_SIZE;i++)
	{
		CloseHandle(hThread[i]);
	}
	cout<<"All Thread end"<<endl;


	system("PAUSE");

	return 0;
}

DWORD WINAPI ThreadFunc(LPVOID n)
{
	int j = (int)n;
	srand(GetTickCount());
	Sleep((rand()%10)*800+500);

	cout<<"Thread "<<j+1<<" is idle"<<endl;
	
	return 0;
}

运行结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值