『轉』Windows API一日一練(45)CreateEvent和SetEvent函數

來源:互聯網
上載者:User

轉自:http://www.ecjtu.org/forum/read.php?tid=18641

 

當你建立一個線程時,其實那個線程是一個迴圈,不像上面那樣只運行一次的。這樣就帶來了一個問題,在那個死迴圈裡要找到合適的條件退出那個死迴圈,那麼是怎麼樣實現它的呢?在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行設定退出線程的事件。 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.