One-Time初始化

元件通常會設計為在第一次呼叫時執行初始化工作,而不是載入它們時。 一次性初始化函式可確保此初始化只會發生一次,即使多個執行緒可能嘗試初始化也一次。

Windows Server 2003 和 Windows XP: 應用程式必須使用 連結 函式或其他同步處理機制,提供自己的一次性初始化同步處理。 從 Windows Vista 和 Windows Server 2008 開始,即可使用一次性初始化函式。

一次性初始化函式提供顯著的優點,以確保只有一個執行緒執行初始化:

  • 它們已針對速度進行優化。
  • 他們會在需要這些障礙的處理器架構上建立適當的屏障。
  • 它們同時支援鎖定和平行初始化。
  • 它們會避免內部鎖定,讓程式碼可以非同步或同步操作。

系統會透過包含資料和狀態資訊的不透明 INIT_ONCE 結構來管理初始化程式。 呼叫端會配置此結構,並藉由呼叫 InitOnceInitialize (來) 動態初始化結構,或將常數 INIT_ONCE_STATIC_INIT 指派給結構變數, (以靜態方式初始化結構) 。 一開始,儲存在一次性初始化結構中的資料是 Null,而且其狀態未初始化。

一次性初始化結構無法跨進程共用。

執行初始化的執行緒可以選擇性地設定初始化完成後,呼叫端可以使用的內容。 內容可以是同步處理物件,也可以是值或資料結構。 如果內容是值,則其低序 INIT_ONCE_CTX_RESERVED_BITS 必須是零。 如果內容是資料結構,則資料結構必須對齊 DWORD。 內容會傳回給InitOnceBeginInitializeInitOnceExecuteOnce函式之lpCoNtext輸出參數中的呼叫端。

一次性初始化可以同步或非同步執行。 選擇性回呼函式可用於同步一次性初始化。

同步一次性初始化

下列步驟描述不使用回呼函式的同步一次性初始化。

  1. 呼叫 InitOnceBeginInitialize 函式的第一個執行緒成功會導致一次性初始化開始。 針對同步一次性初始化,必須呼叫 InitOnceBeginInitialize 而不呼叫 INIT_ONCE_ASYNC 旗標。
  2. 嘗試初始化的後續執行緒會遭到封鎖,直到第一個執行緒完成初始化或失敗為止。 如果第一個執行緒失敗,則允許下一個執行緒嘗試初始化等等。
  3. 初始化完成時,執行緒會呼叫 InitOnceComplete 函式。 執行緒可以選擇性地建立同步處理物件 (或其他內容資料) ,並在InitOnceComplete函式的lpCoNtext參數中加以指定。
  4. 如果初始化成功,則一次性初始化結構的狀態會變更為已初始化,而且如果有任何) 儲存在初始化結構中, 則 lpCoNtext 控制碼會 (。 後續的初始化嘗試會傳回此內容資料。 如果初始化失敗,則資料為 Null

下列步驟描述使用回呼函式的同步一次性初始化。

  1. 成功呼叫 InitOnceExecuteOnce 函式的第一個執行緒會將指標傳遞至應用程式定義的 InitOnceCallback 回 呼函式,以及回呼函式所需的任何資料。 如果呼叫成功, InitOnceCallback 回 呼函式就會執行。
  2. 嘗試初始化的後續執行緒會遭到封鎖,直到第一個執行緒完成初始化或失敗為止。 如果第一個執行緒失敗,則允許下一個執行緒嘗試初始化等等。
  3. 初始化完成時,回呼函式會傳回。 回呼函式可以選擇性地建立同步處理物件 (或其他內容資料) ,並在其 內容 輸出參數中指定它。
  4. 如果初始化成功,則一次性初始化結構的狀態會變更為初始化,如果任何) 儲存在初始化結構中, 內容 控制碼就會 (。 後續的初始化嘗試會傳回此內容資料。 如果初始化失敗,則資料為 Null

非同步單次初始化

下列步驟描述非同步一次性初始化。

  1. 如果多個執行緒同時嘗試使用INIT_ONCE_ASYNC呼叫InitOnceBeginInitialize來開始初始化,則所有線程的函式都會成功,並將 fPending參數設定為TRUE。 在初始化時,只有一個執行緒實際上會成功;其他並行嘗試不會變更初始化狀態。
  2. 當 InitOnceBeginInitialize傳回時,fPending參數會指出初始化狀態:
    • 如果 fPendingFALSE,則一個執行緒在初始化時成功。 其他執行緒應該清除他們建立的任何內容資料,並在InitOnceBeginInitializelpCoNtext輸出參數中使用內容資料。
    • 如果 fPendingTRUE,則初始化尚未完成,其他執行緒應該會繼續。
  3. 每個執行緒都會呼叫 InitOnceComplete 函式 。 執行緒可以選擇性地建立同步處理物件 (或其他內容資料) ,並在InitOnceCompletelpCoNtext參數中加以指定。
  4. 當 InitOnceComplete傳回時,其傳回值會指出呼叫執行緒是否在初始化時成功。
    • 如果 InitOnceComplete 成功,則呼叫執行緒在初始化時成功。 一次性初始化結構的狀態會變更為已初始化,如果初始化結構中有任何) 儲存在初始化結構中, lpCoNtext 控制碼就會 (。
    • 如果 InitOnceComplete 失敗,另一個執行緒在初始化時成功。 呼叫執行緒應該清除它已建立的任何內容資料,並使用INIT_ONCE_CHECK_ONLY呼叫InitOnceBeginInitialize,以擷取儲存在一次性初始化結構中的任何內容資料。

從多個網站呼叫One-Time初始化

單一 INIT_ONCE 結構所保護的單次初始化,可以從 Mutiple 月臺執行;不同的回呼可能會從每個月臺傳遞,而且與 和 沒有回呼的同步處理可能會混合。 初始化仍然有效率地只執行一次。

不過,非同步和同步初始化無法混合:一旦嘗試非同步初始化,嘗試啟動同步初始化將會失敗。

使用One-Time初始化