Win32下对多个的线程句柄的关闭的控制(下)

发表于:2007-07-01来源:作者:点击数: 标签:
下面是CMultipleHandles和一个基于Console的源码。 // MultipleHandles.h // 作者: 黄瑞广 时间: 2004-02-06 // 说明: 本类不支持线程 安全 class CMultipleHandles { private: int m_nNumOfHandle; public: HANDLE m_arrayHandle[MAXIMUM_WAIT_OBJECTS]; ..

下面是CMultipleHandles和一个基于Console的源码。

       // MultipleHandles.h

// 作者: 黄瑞广   时间: 2004-02-06

// 说明: 本类不支持线程安全

class CMultipleHandles

{

private:

       int m_nNumOfHandle;            

public:

       HANDLE m_arrayHandle[MAXIMUM_WAIT_OBJECTS];   

       ...........

};

 // MultipleHandles.cpp

#include "stdafx.h"

#include "MultipleHandles.h" 

CMultipleHandles::CMultipleHandles()

{

       Init();

void CMultipleHandles::Init()

{

       m_nNumOfHandle = 0;    // 句柄数为"0" 

       for (int i = 0; i < MAXIMUM_WAIT_OBJECTS; i++)

              m_arrayHandle[i] = NULL;   // NULL表示该句柄位可用

}

// 功能: 判断句柄槽位是否是空

// 返回值: TRUE, 空; FALSE, 不空

BOOL CMultipleHandles::IsEmpty()

{

       if (m_nNumOfHandle == 0)

              return TRUE;

 

       return FALSE;

}

// 功能: 判断句柄槽位是否已满

// 返回值: TRUE, 已满; FALSE, 未满

BOOL CMultipleHandles::IsFull()

{

       if (m_nNumOfHandle == MAXIMUM_WAIT_OBJECTS)

              return TRUE;  

 

       return FALSE;

}

// 功能: 获得可用槽位的索引值

// 返回值: -1, 没有可用的槽位; 否则是空槽位的索引

int CMultipleHandles::GetFree()

{

       int nIndex;

 

       if (IsFull())

              return -1;     // 整个句柄槽没有可用的槽位, 返回-1

 

       for (int i = 0; i < MAXIMUM_WAIT_OBJECTS; i++)

       {

              if (m_arrayHandle[i] == NULL)

              {

                     nIndex = i;

                     break;

              }

       }

 

       return nIndex;

}

// 功能: 获得句柄槽中句柄的个数

// 返回值: 句柄个数

int CMultipleHandles::GetNumOfHandle()

{

       return m_nNumOfHandle;

}

// 功能: 把一个句柄插入到句柄槽中

// 参数: 句柄, 作为输入

// 返回值: -1, 线程槽已满,插入失败; 成功, 返回插入索引值

int CMultipleHandles::Insert(const HANDLE hParam)

{

       int nIndex;

 

       nIndex = GetFree();

       if (nIndex == -1)

              return -1;

 

       m_arrayHandle[nIndex] = hParam;

       m_nNumOfHandle++;

 

       return nIndex;

}

// 功能: 清除句柄槽中指定的句柄

// 参数: 输入, 句柄索引

// 返回值: TRUE, 成功; FALSE, 失败

BOOL CMultipleHandles::Clear(int nIndex)

{

       if (IsEmpty())

              return FALSE;

 

       m_arrayHandle[nIndex] = NULL;

       m_nNumOfHandle--; 

       return TRUE;

}

 // 功能: 重置线程槽的槽位

// 返回值: TRUE, 重置成功; FALSE, 失败

BOOL CMultipleHandles::Reset()

{

       if (m_nNumOfHandle == 0)  // 句柄槽中已没有可用句柄

              return FALSE;

 

       HANDLE arrayTempHandle[MAXIMUM_WAIT_OBJECTS];

   

       // 在句柄槽中未清除句柄前的句柄个数是m_nNumOfHandle + 1

       // 把须要重置的句柄索引的上限定为m_nNumOfHandle是为了提高程序的效率,

       // 因为在大多数情况下, 须重置的句柄个数会<<MAXIMUM_WAIT_OBJECTS(64).

       for (int i = 0, j = 0; i < m_nNumOfHandle + 1; i++)

       {

              if (m_arrayHandle[i] == NULL)

                     continue;

 

              // 将句柄槽中的句柄复制到一个监时数据组中

              arrayTempHandle[j] = m_arrayHandle[i]; 

              j++;

       }

       // 将原来的数组空间初始化

       for (i = 0; i < m_nNumOfHandle + 1; i++)

              m_arrayHandle[i] = NULL;

       // 将临时数组的数据拷贝

       for (i = 0; i < m_nNumOfHandle; i++)

              m_arrayHandle[i] = arrayTempHandle[i];

       return TRUE;

}

上面这类在效率上不高需要改进。 

// Console 主函数

int main()

{

       BOOL bIsFrist = FALSE;   

       // Start winsock and create listen socket

       nRet = listen(listensock,  5);

       CMultipleHandles multipleHandles; // 声明线程槽对 

       while (TRUE)

       {

              if (!bIsFrist)   // 不是第一次执行循环

              {

                     for (;;)

                     {

                            if (multipleHandles.IsEmpty())  // 线程句柄槽是空的, 不循环

                                   break;

                      nRet = WaitForMultipleObjects(

                             multipleHandles.GetNumOfHandle(),

                             multipleHandles.m_arrayHandle,

                             FALSE,     // 有一个事件处于激发态, 函数就返回

                             0          // 函数检查所有事件的状态后, 立即返回

                                );

                         if (nRet == WAIT_FAILED | nRet == WAIT_TIMEOUT)

                                break;

                else

                            {

                                // 关闭线程槽的某个槽位中已处于激发状态的线程句柄                       CloseHandle(multipleHandles.m_arrayHandle[nRet - WAIT_OBJECT_0]);

                    // 清除句柄槽位中的句柄

                                 multipleHandles.Clear(nRet - WAIT_OBJECT_0);

                                   if (!multipleHandles.Reset())    // 重置句柄槽位

                                          break;

                            }

                     } // end for (;;)

              }// end if (!bIsFrist)

              else

                     bIsFrist = FALSE;

                             

              clisock = aclearcase/" target="_blank" >ccept(listensock, NULL, NULL);

              if (clisock == INVALID_SOCKET)

                     continue;

  

              if (multipleHandles.IsFull())

              {

                     printf("线程句柄槽位已满, 将拒绝本次客户的连接!\n");

                     closesocket(ClientSock);

                     continue;

              }

 

              hThread = CreateThread(NULL,  0,  DoThread,  &clisock,  0,  NULL);

              if (hThread == NULL)

                     continue;                     

              // 将线程句柄插入到线程槽的槽位中.

              multipleHandles.Insert(hThread);

       }

       return 0;

}

 

DWORD WINAPI DoThread(LVOID lpParam)

{

      // 处理clisock的通信问题

      // ……

}

 

这就是我最终解决的问题,希望大家能多给点改进的意见。

 


原文转自:http://www.ltesting.net