当前位置:首页 > windos > 正文

Windows API一日一练 60 CreateIoCompletionPort和GetQueuedCompletio

在 Windows 系统里,使用完成端口是高性能的方法之一,比如把完成端口使用到线程池和网络服务器里。现在就通过线程池的方法来介绍怎么样使用完成端口,高性能的服务器以后再仔细地介绍怎么样构造它。其实完成端口是一个队列,所有的线程都在等消息出现,如果队列里有消息,就每个线程去获取一个消息执行它。先用函数 CreateIoCompletionPort 来创建一个消息队列,然后使用 GetQueuedCompletionStatus 函数来从队列获取消息,使用函数 PostQueuedCompletionStatus 来向队列里发送消息。通过这三个函数就实现完成端口的消息循环处理。   函数 CreateIoCompletionPort 、 GetQueuedCompletionStatus 、 PostQueuedCompletionStatus 声明如下:   WINBASEAPI __out HANDLE WINAPI CreateIoCompletionPort(     __in     HANDLE FileHandle,     __in_opt HANDLE ExistingCompletionPort,     __in     ULONG_PTR CompletionKey,     __in     DWORD NumberOfConcurrentThreads     ); WINBASEAPI BOOL WINAPI GetQueuedCompletionStatus(     __in HANDLE CompletionPort,     __out LPDWORD lpNumberOfBytesTransferred,     __out PULONG_PTR lpCompletionKey,     __out LPOVERLAPPED *lpOverlapped,     __in DWORD 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 深圳 #008 class CThreadPools #009 { #010 public: #011  #012  CThreadPools(void) #013  { #014          m_nThreadCount = 2; #015   } #016  #017  ~CThreadPools(void) #018  { #019  } #020  #021  bool 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  #032  int GetThreadCount(void) const #033  { #034         return m_nThreadCount; #035  } #036  #037  // 线程池处理的内容。 #038  DWORD 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  // 发送处理的消息。 #068  bool 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  // 关闭所有线程。 #080  void Close(void) #081  { #082         for (int i = 0; i < m_nThreadCount; i++) #083         { #084               PostQueuedCompletionStatus(m_hQueue, 0, 0, (OVERLAPPED*) ((__int64) -1) ); #085         } #086  } #087  #088 protected: #089  // 接收消息处理的队列。 #090  HANDLE m_hQueue; #091  #092  // 线程个数。 #093  int m_nThreadCount; #094 }; #095  #096 ////////////////////////////////////////////////////////////////////////// #097 class CThreads : #098  public CThread #099 { #100 public: #101  CThreads(CThreadPools* pPool) #102  { #103          m_pPool = pPool;         #104  } #105  virtual ~CThreads(void) #106  { #107  #108  } #109  #110  #111 protected: #112  // #113  // 线程运行函数。 #114  // 在这里可以使用类里的成员,也可以让派生类实现更强大的功能。 #115  // 蔡军生 2007/10/29 #116  virtual DWORD Run(void) #117  { #118         // #119         if (m_pPool) #120         { #121               return m_pPool->Run(); #122         } #123  #124         return -1; #125  } #126  #127 protected: #128  CThreadPools* m_pPool; #129  #130 };  

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow