Windows API一日一练(60)CreateIoCompletionPort和GetQueuedCompletionStatus函数

<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>
Windows系统里,使用完成端口是高性能的方法之一,比如把完成端口使用到线程池和网络服务器里。现在就通过线程池的方法来介绍怎么样使用完成端口,高性能的服务器以后再仔细地介绍怎么样构造它。其实完成端口是一个队列,所有的线程都在等消息出现,如果队列里有消息,就每个线程去获取一个消息执行它。先用函数CreateIoCompletionPort来创建一个消息队列,然后使用GetQueuedCompletionStatus函数来从队列获取消息,使用函数PostQueuedCompletionStatus来向队列里发送消息。通过这三个函数就实现完成端口的消息循环处理。
函数CreateIoCompletionPortGetQueuedCompletionStatusPostQueuedCompletionStatus声明如下:
WINBASEAPI
__out
HANDLE
WINAPI
CreateIoCompletionPort(
__in HANDLE FileHandle,
__in_opt HANDLE ExistingCompletionPort,
__in ULONG_PTR CompletionKey,
__in DWORD NumberOfConcurrentThreads
);
WINBASEAPI
BOOL
WINAPI
GetQueuedCompletionStatus(
__inHANDLE CompletionPort,
__out LPDWORD lpNumberOfBytesTransferred,
__out PULONG_PTR lpCompletionKey,
__out LPOVERLAPPED *lpOverlapped,
__inDWORD dwMilliseconds
);
WINBASEAPI
BOOL
WINAPI
PostQueuedCompletionStatus(
__in HANDLE CompletionPort,
__in DWORD dwNumberOfBytesTransferred,
__in ULONG_PTR dwCompletionKey,
__in_opt LPOVERLAPPED lpOverlapped
);
FileHandle是关联的文件句柄。
ExistingCompletionPort是已经存在的完成端口。
CompletionKey是传送给处理函数的参数。
NumberOfConcurrentThreads是有多少个线程在访问这个消息队列。
CompletionPort是已经存在的完成端口。
lpCompletionKey是传送给处理函数的参数。
lpOverlapped是传送给处理函数的参数。
dwMilliseconds是等待时间。
dwNumberOfBytesTransferred是传送了多少个字节。
调用函数的例子如下:
#001#pragma once
#002
#003#include "Thread.h"
#004
#005
#006//使用IOCP实现线程池。
#007//蔡军生2007/10/29 QQ:9073204 深圳
#008class CThreadPools
#009{
#010public:
#011
#012CThreadPools(void)
#013{
#014 m_nThreadCount = 2;
#015 }
#016
#017~CThreadPools(void)
#018{
#019}
#020
#021bool Init(void)
#022{
#023 //创建一个IOCP
#024 m_hQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, m_nThreadCount);
#025 if (m_hQueue == NULL)
#026 {
#027 //创建IOCP失败。
#028 return false;
#029 }
#030}
#031
#032int GetThreadCount(void) const
#033{
#034 return m_nThreadCount;
#035}
#036
#037//线程池处理的内容。
#038DWORD Run(void)
#039{
#040 DWORD dwBytesTransfered;
#041 ULONG_PTR dwCompletionKey;
#042
#043 OVERLAPPED* pOverlapped;
#044
#045 //等一个IOCP的消息。
#046 while (GetQueuedCompletionStatus(m_hQueue, &dwBytesTransfered, &dwCompletionKey, &pOverlapped, INFINITE))
#047 {
#048 if (pOverlapped == ((OVERLAPPED*) ((__int64) -1)) )
#049 {
#050 //退出。
#051 OutputDebugString(_T("退出 \r\n"));
#052 break;
#053 }
#054 else
#055
#056 {
#057 WPARAM request = (WPARAM) dwCompletionKey;
#058
#059 //处理消息。
#060 OutputDebugString(_T("GetQueuedCompletionStatus \r\n"));
#061 }
#062 }
#063
#064 return 0;
#065}
#066
#067//发送处理的消息。
#068bool QueueRequest(WPARAM wParam)
#069{
#070 //IOCP里发送一条消息。
#071 if (!PostQueuedCompletionStatus(m_hQueue, 0, (ULONG_PTR) wParam, NULL))
#072 {
#073 return false;
#074 }
#075
#076 return true;
#077}
#078
#079//关闭所有线程。
#080void Close(void)
#081{
#082 for (int i = 0; i
#083 {
#084 PostQueuedCompletionStatus(m_hQueue, 0, 0, (OVERLAPPED*) ((__int64) -1) );
#085 }
#086}
#087
#088protected:
#089//接收消息处理的队列。
#090HANDLE m_hQueue;
#091
#092//线程个数。
#093int m_nThreadCount;
#094};
#095
#096//////////////////////////////////////////////////////////////////////////
#097class CThreads :
#098public CThread
#099{
#100public:
#101CThreads(CThreadPools* pPool)
#102{
#103 m_pPool = pPool;
#104}
#105virtual ~CThreads(void)
#106{
#107
#108}
#109
#110
#111protected:
#112//
#113//线程运行函数。
#114//在这里可以使用类里的成员,也可以让派生类实现更强大的功能。
#115//蔡军生 2007/10/29
#116virtual DWORD Run(void)
#117{
#118 //
#119 if (m_pPool)
#120 {
#121 returnm_pPool->Run();
#122 }
#123
#124 return -1;
#125}
#126
#127protected:
#128CThreadPools* m_pPool;
#129
#130};



解决:软件多线程运行时遇到【内存不断升高】甚至爆表! 因为本人是个小白,多线程经常用,但是线程池并没有用过,(一听到线程池,总感觉高大上) 但是近期写彩票软件的时候发现,多线程长期操作会导致内容不断的升高直至报错,遂想起了线程池,完善后发现不是一般的叼 啊!!! 先简单的说下多线程线程池的区别: 1、多线程每次启动的时候系统都要分配一定的资源出来(主要占的就是内存),而不断的启动线程、启动线程、启动线程 循环的启动线程,就造成了系统资源极大的浪费,甚至不释放的情况,继续下去内存就OVER了! 2、线程池则完美的解决了这个问题,线程池的原理就是事先申请好指定数量的线程所使用的资源,而且这些资源是不断的重复利用的!可利用任务管理器看到程序的线程数量的变化(在使用普通的多线程时:线程数会根据软件启动的线程数量增加,循环完了之后线程数量也就减少了,但是内存资源不减少,再启动线程内存继续飙升!  而在使用【线程池】的时候:线程数一直保持线程池中的数量,无论你是否启动多线程进行运算,线程数量都不会变化,同时内存也不会有多大的变化,更不会不断的飙升!) 也许我的表达能力不足,反正大家知道在启用多线程的时候尽量使用线程池可以保证内存不会飙升就行了! 这里说的启动多线程是指循环启动‘同一个子程序’线程:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值