Compartir a través de


inicialización de One-Time

A menudo, los componentes se diseñan para realizar tareas de inicialización cuando se les llama por primera vez, en lugar de cuando se cargan. Las funciones de inicialización única garantizan que esta inicialización solo se produce una vez, incluso cuando varios subprocesos pueden intentar la inicialización.

Windows Server 2003 y Windows XP: las aplicaciones de deben proporcionar su propia sincronización para la inicialización única mediante las funciones interbloqueadas u otro mecanismo de sincronización. Las funciones de inicialización única están disponibles a partir de Windows Vista y Windows Server 2008.

Las funciones de inicialización única proporcionan ventajas significativas para asegurarse de que solo un subproceso realiza la inicialización:

  • Están optimizados para velocidad.
  • Crean las barreras adecuadas en las arquitecturas de procesador que las requieren.
  • Admiten inicialización bloqueada y paralela.
  • Evitan el bloqueo interno para que el código pueda funcionar de forma asincrónica o sincrónica.

El sistema administra el proceso de inicialización a través de una estructura de INIT_ONCE opaca que contiene información de datos y estado. El autor de la llamada asigna esta estructura e la inicializa llamando a InitOnceInitialize (para inicializar la estructura dinámicamente) o asignando la constante INIT_ONCE_STATIC_INIT a la variable de estructura (para inicializar la estructura estáticamente). Inicialmente, los datos almacenados en la estructura de inicialización única son NULL y su estado no se inicializa.

Las estructuras de inicialización única no se pueden compartir entre procesos.

El subproceso que realiza la inicialización puede establecer opcionalmente un contexto que esté disponible para el autor de la llamada una vez completada la inicialización. El contexto puede ser un objeto de sincronización o puede ser un valor o una estructura de datos. Si el contexto es un valor, su INIT_ONCE_CTX_RESERVED_BITS de orden bajo debe ser cero. Si el contexto es una estructura de datos, la estructura de datos debe estar DWORDalineado. El contexto se devuelve al autor de la llamada en el parámetro de salida de lpContext del InitOnceBeginInitialize o función InitOnceExecuteOnceOnce.

La inicialización única se puede realizar de forma sincrónica o asincrónica. Se puede usar una función de devolución de llamada opcional para la inicialización única sincrónica.

Inicialización sincrónica única

En los pasos siguientes se describe la inicialización única sincrónica que no usa una función de devolución de llamada.

  1. El primer subproceso para llamar a la función InitOnceBeginInitialize hace que se inicie correctamente la inicialización única. Para la inicialización única sincrónica, se debe llamar a InitOnceBeginInitialize sin la marca INIT_ONCE_ASYNC.
  2. Los subprocesos posteriores que intentan inicializar se bloquean hasta que el primer subproceso completa la inicialización o se produce un error. Si se produce un error en el primer subproceso, el siguiente subproceso puede intentar la inicialización, etc.
  3. Cuando finaliza la inicialización, el subproceso llama a la funcióninitOnceComplete. El subproceso puede crear opcionalmente un objeto de sincronización (u otros datos de contexto) y especificarlo en el parámetro lpContext de la función InitOnceComplete.
  4. Si la inicialización se realiza correctamente, el estado de la estructura de inicialización única se cambia a inicializado y el identificador de lpContext (si existe) se almacena en la estructura de inicialización. Los intentos de inicialización posteriores devuelven estos datos de contexto. Si se produce un error en la inicialización, los datos se NULL.

En los pasos siguientes se describe la inicialización sincrónica única que usa una función de devolución de llamada.

  1. El primer subproceso para llamar correctamente a la función InitOnceExecuteOnce pasa un puntero a un InitOnceCallback función de devolución de llamada y los datos requeridos por la función de devolución de llamada. Si la llamada se realiza correctamente, se ejecuta la función de devolución de llamada InitOnceCall back.
  2. Los subprocesos posteriores que intentan inicializar se bloquean hasta que el primer subproceso completa la inicialización o se produce un error. Si se produce un error en el primer subproceso, el siguiente subproceso puede intentar la inicialización, etc.
  3. Cuando finaliza la inicialización, la función de devolución de llamada devuelve. La función de devolución de llamada puede crear opcionalmente un objeto de sincronización (u otros datos de contexto) y especificarlo en su parámetro de salida Context.
  4. Si la inicialización se realiza correctamente, el estado de la estructura de inicialización única se cambia a inicializado y el identificador de Context (si existe) se almacena en la estructura de inicialización. Los intentos de inicialización posteriores devuelven estos datos de contexto. Si se produce un error en la inicialización, los datos se NULL.

Inicialización asincrónica única

En los pasos siguientes se describe la inicialización asincrónica única.

  1. Si varios subprocesos intentan iniciar la inicialización simultáneamente llamando a InitOnceBeginInitialize con INIT_ONCE_ASYNC, la función se realiza correctamente para todos los subprocesos con el parámetro fPending establecido en TRUE. Solo un subproceso se realizará correctamente en la inicialización; Otros intentos simultáneos no cambian el estado de inicialización.
  2. Cuando initOnceBeginInitialize devuelve, el parámetro fPending indica el estado de inicialización:
    • Si pendiente es FALSE, un subproceso se ha realizado correctamente al inicializarse. Otros subprocesos deben limpiar los datos de contexto que hayan creado y usar los datos de contexto en el lpContext parámetro de salida de InitOnceBeginInitialize.
    • Si fPending es TRUE, la inicialización aún no se ha completado y otros subprocesos deben continuar.
  3. Cada subproceso llama a la funcióninitOnceComplete. El subproceso puede crear opcionalmente un objeto de sincronización (u otros datos de contexto) y especificarlo en el parámetro lpContext de InitOnceComplete.
  4. Cuando initOnceComplete devuelve, su valor devuelto indica si el subproceso que realiza la llamada se realizó correctamente durante la inicialización.
    • Si initOnceComplete se realiza correctamente, el subproceso que realiza la llamada se ha realizado correctamente durante la inicialización. El estado de la estructura de inicialización única se cambia a inicializado y el identificador de lpContext (si existe) se almacena en la estructura de inicialización.
    • Si se produce un error en InitOnceComplete, otro subproceso se ha realizado correctamente en la inicialización. El subproceso de llamada debe limpiar los datos de contexto que haya creado y llamar a InitOnceBeginInitialize con INIT_ONCE_CHECK_ONLY para recuperar los datos de contexto almacenados en la estructura de inicialización única.

Llamada a One-Time inicialización desde varios sitios

La inicialización única protegida por una sola estructura de INIT_ONCE se puede realizar desde varios sitios; Se puede pasar una devolución de llamada diferente desde cada sitio y puede mezclarse la sincronización con y sin devolución de llamada. Todavía se garantiza que la inicialización se realice correctamente una sola vez.

Sin embargo, no se puede mezclar la inicialización asincrónica y sincrónica: una vez que se intenta la inicialización asincrónica, se producirá un error en los intentos de iniciar la inicialización sincrónica.

usar de inicialización de One-Time