程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> Win32 API 常用函數之二

Win32 API 常用函數之二

編輯:.NET實例教程

【事件】
       事件用處多是控制線程間的同步。
       最典型的應用就是CreateThread之後等待線程函數的啟動。如Main線程裡CreateThread,它之後的操作依賴於子線程,那麼它一般會在CreateThread之後判斷HANDLE是否有效,然後進入等待。(當然在這之前,一個Event是已經創建好的,並初始化為未通知狀態)子線程啟動後完成了初始化操作,並設置Event為已通知狀態。這時,一直在等待該事件的Main線程發現該事件已經得到通知,因此它就變成可調度線程。這時Main線程知道子線程已經完成了初始化操作。
       CreateEvent函數用於創建一個Event,其原型如下:


HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, 
  BOOL bManualReset, 
  BOOL bInitialState, 
  LPTSTR lpName 
);        參數說明:

  1. 第一個參數同CreateThread類似,也是安全級別相關,通常被被設置為NULL,以獲得默認的安全級別。
  2. 第二個參數是個布爾值,它能夠告訴系統是創建一個人工重置的事件(TRUE)還是創建一個自動重置的事件( FALSE)。
  3. 第三個參數也是布爾值,用於指明該事件是要初始化為已通知狀態(TRUE)還是未通知狀態(FALSE)。
  4. 第四個參數是一個字符串,用於標示這個事件的名字。
       以下是詳細說明:
  1. 已通知狀態和未通知狀態
    事件只有兩種狀態,已通知表示這個事件已經被設置過了(可以理解為發生了),未通知表示還沒有發生。一般設置為未通知狀態,並由SetEvent設置為已通知狀態。當然也可以反著做,CreateEvent時設置為已通知狀態,然後由ResetEvent設置為未通知狀態。
  2. 人工重置與自動重置
    自動重置的事件定義了應該成功等待的副作用規則,即當線程成功地等待到該對象時,自動重置的事件就會自動重置到未通知狀態。
    人工重置則需要調用ResetEvent函數設置為未通知狀態。
  3. 名字共享
    這個參數很重要,Win32 API中有很多方法有這個參數,它遵從一種按名字共享的規則。
    如果傳入一個非NULL字符串(最多260個字符),那麼在全局空間,共享該HANDLE,這個全局可以是跨進程的名字空間,即在另一個進程中依然能夠使用該名字的HANDLE。
    如果希望避免這種全局范圍內的共享,那麼應該傳入NULL,以一種匿名的方式創建Event等,這樣,它只在當前線程內可見。
        當進程A創建了一個Event後,如CreateEvent(NULL,FALSE,FLASE,_T(“UniqueEvent”));進程B同樣創建了一個Event,也想起名字為UniqueEvent,那麼就會出現問題:CreateEvent(NULL,FALSE,FALSE,_T(“UniqueEvent”));系統會首先查看是否已經存在了一個名字為“UniqueEvent”的對象,由於確實存在了一個帶有改名字的內核對象,因此內核要檢查對象類型,同樣是一 個Event,那麼系統會執行一次安全檢查,以確定調用者是否擁有對該對象的完整訪問權。如果有這種訪問權,系統會在進程B的句柄表裡找到一個空項目,對 其初始化,使得該項指向現有的內核對象。如果類型不匹配,或者拒絕訪問,那麼進程B的CreateEvent會失敗。
       應用程序能夠確定它是否確實創建了一個新內核對象,而不是打開了一個現有的對象。方法是在調用C r e a t e *函數後立即調用G e t L a s t E r r o r:如果為ERROR_ALREADY_EXISTS,那麼表示系統內已經存在了這樣名字的對象。
       Open*是去查看名字空間中是否有這個名字的內核對象存在調用C r e a t e *函數與調用O p e n *函數之間的主要差別是,如果對象並不存在,那麼C r e a t e *函數將創建該對象,而O p e n *函數則運行失敗。

       PulseEvent函數使得事件變為已通知狀態,然後立即又變為未通知狀態,這就像在調用SetEvent後又立即調用ResetEvent函數一樣。如果在人工重置的事件上調用PulseEvent函數,那麼在發出該事件時,等待該事件的任何一個線程或所有線程將變為可調度線程。如果在自動重置事件上調用P u l s e E v e n t函數,那麼只有一個等待該事件的線程變為可調度線程。如果在發出事件時沒有任何線程在等待該事件,那麼將不起任何作用。

【等待函數】
       等待函數用來監聽事件的已通知狀態。WaitForSingleObject和WaitForMultipleObjects兩個函數分別用以等待單個事件和多個事件。


DWord WaitForSingleObject(
  HANDLE hHandle,
  DWord dwMilliseconds
);
DWord WaitForMultipleObjects(
  DWord nCount,
  const HANDLE* lpHandles,
  BOOL bWaitAll,
  DWord dwMilliseconds
);       從函數原型上來看可知,事件的含義是能夠支持被通知/未通知的內核對象(例如進程和線程,當傳入的是進程或者線程句柄時,他表示等該線程或進程被標識為終止運行為止。)。
       dwMilliseconds參數表明等待的時間,如果在這個時間段中事件為已通知狀態,那麼對於Single版本將返回WAIT_OBJECT_0,對於Multiple版本將返回WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount– 1)。如果沒有等到將返回WAIT_TIMEOUT。
       Multiple版本中的bWaitAll表示想要讓它使用何種方式等待。如果為該參數傳遞TRUE,那麼在所有對象變為已通知狀態之前,該函數將不允許調用線程運行。一般是FALSE,即只要有一個事件被相應,則線程可調度。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved