裸奔的蜗牛的专栏

天天开心-OYE

Windows API一日一练(45)CreateEvent和SetEvent函数
当你创建一个线程时,其实那个线程是一个循环,不像上面那样只运行一次的。这样就带来了一个问题,在那个死循环里要找到合适的条件退出那个死循环,那么是怎么样实现它的呢?在Windows里往往是采用事件的方式,当然还可以采用其它的方式。在这里先介绍采用事件的方式来通知从线程运行函数退出来,它的实现原理是这样,在那个死循环里不断地使用WaitForSingleObject函数来检查事件是否满足,如果满足就退出线程,不满足就继续运行。当在线程里运行阻塞的函数时,就需要在退出线程时,先要把阻塞状态变成非阻塞状态,比如使用一个线程去接收网络数据,同时使用阻塞的SOCKET时,那么要先关闭SOCKET,再发送事件信号,才可以退出线程的。下面就来演示怎么样使用事件来通知线程退出来。
 
函数CreateEvent声明如下:
 
WINBASEAPI
__out
HANDLE
WINAPI
CreateEventA(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCSTR lpName
    );
WINBASEAPI
__out
HANDLE
WINAPI
CreateEventW(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCWSTR lpName
    );
#ifdef UNICODE
#define CreateEvent CreateEventW
#else
#define CreateEvent CreateEventA
#endif // !UNICODE
lpEventAttributes是事件的属性。
bManualReset是指事件手动复位,还是自动复位状态。
bInitialState是初始化的状态是否处于有信号的状态。
lpName是事件的名称,如果有名称,可以跨进程共享事件状态。
 
调用这个函数的例子如下:
#001 #pragma once
#002 
#003 //线程类。
#004 //蔡军生 2007/09/23 QQ:9073204
#005 class CThread
#006 {
#007 public:
#008 
#009  CThread(void)
#010  {
#011          m_hThread = NULL;
#012          m_hEventExit = NULL;
#013  }
#014 
#015  virtual ~CThread(void)
#016  {
#017         if (m_hThread)
#018         {
#019               //删除的线程资源。
#020               ::CloseHandle(m_hThread);
#021         }
#022 
#023         if (m_hEventExit)
#024         {
#025               //删除事件。
#026               ::CloseHandle(m_hEventExit);
#027         }
#028        
#029  }
#030 
#031  //创建线程
#032  HANDLE CreateThread(void)
#033  {
#034         //创建退出事件。
#035         m_hEventExit = ::CreateEvent(NULL,TRUE,FALSE,NULL);
#036         if (!m_hEventExit)
#037          {
#038               //创建事件失败。
#039               return NULL;
#040         }
#041 
#042         //创建线程。
#043          m_hThread = ::CreateThread(
#044               NULL,                    //安全属性使用缺省。
#045               0,                         //线程的堆栈大小。
#046               ThreadProc,                 //线程运行函数地址。
#047               this,                      //传给线程函数的参数。
#048               0,                         //创建标志。
#049               &m_dwThreadID);        //成功创建后的线程标识码。
#050 
#051         return m_hThread;
#052  }
#053 
#054  //等待线程结束。
#055  void WaitFor(DWORD dwMilliseconds = INFINITE)
#056  {
#057         //发送退出线程信号。
#058        ::SetEvent(m_hEventExit);
#059 
#060         //等待线程结束。
#061         ::WaitForSingleObject(m_hThread,dwMilliseconds);
#062  }
#063 
#064 protected:
#065  //
#066  //线程运行函数。
#067  //蔡军生 2007/09/21
#068  //
#069  static DWORD WINAPI ThreadProc(LPVOID lpParameter)
#070  {
#071         //转换传送入来的参数。
#072         CThread* pThread = reinterpret_cast<CThread *>(lpParameter);
#073         if (pThread)
#074         {
#075               //线程返回码。
#076               //调用类的线程处理函数。
#077               return pThread->Run();
#078         }
#079        
#080         //
#081         return -1;       
#082  }
#083 
#084  //线程运行函数。
#085  //在这里可以使用类里的成员,也可以让派生类实现更强大的功能。
#086  //蔡军生 2007/09/25
#087  virtual DWORD Run(void)
#088  {
#089         //输出到调试窗口。
#090         ::OutputDebugString(_T("Run()线程函数运行/r/n"));     
#091 
#092         //线程循环。
#093         for (;;)
#094         {
#095              DWORD dwRet = WaitForSingleObject(m_hEventExit,0);
#096               if (dwRet == WAIT_TIMEOUT)
#097               {
#098                    //可以继续运行。                
#099                    TCHAR chTemp[128];
#100                    wsprintf(chTemp,_T("ThreadID=%d/r/n"),m_dwThreadID);
#101                    ::OutputDebugString(chTemp);
#102 
#103                     //目前没有做什么事情,就让线程释放一下CPU
#104                    Sleep(10);
#105               }
#106               else if (dwRet == WAIT_OBJECT_0)
#107               {
#108                    //退出线程。
#109                    ::OutputDebugString(_T("Run() 退出线程/r/n"));
#110                    break;
#111               }
#112               else if (dwRet == WAIT_ABANDONED)
#113               {
#114                    //出错。
#115                    ::OutputDebugString(_T("Run() 线程出错/r/n"));
#116                    return -1;
#117               }
#118         }
#119 
#120         return 0;
#121  }
#122 
#123 protected:
#124  HANDLE m_hThread;         //线程句柄。
#125  DWORD m_dwThreadID;          //线程ID
#126 
#127  HANDLE m_hEventExit;    //线程退出事件。
#128 };
#129 
 
上面在第35行创建线程退出事件,第95行检查事件是否可退出线程运行,第58行设置退出线程的事件。 
阅读更多
个人分类: api
想对作者说点什么? 我来说一句

Windows API一日一练TXT版

2010年04月09日 59KB 下载

Windows API 一日一练

2010年04月17日 1.63MB 下载

API函数一日一练pdf

2010年07月14日 1.63MB 下载

Windows API一日一练

2010年07月25日 2.52MB 下载

windows API 一日一练(93练)

2009年12月13日 2.53MB 下载

没有更多推荐了,返回首页

不良信息举报

Windows API一日一练(45)CreateEvent和SetEvent函数

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭