Nota
O acceso a esta páxina require autorización. Pode tentar iniciar sesión ou modificar os directorios.
O acceso a esta páxina require autorización. Pode tentar modificar os directorios.
La EventWaitHandle clase permite que los subprocesos se comuniquen entre sí mediante la señalización y la espera de señales. Los identificadores de espera de eventos (también denominados simplemente como eventos) son identificadores de espera que se pueden señalar con el fin de liberar uno o varios subprocesos en espera. Cuando se envía una señal, se restablece un identificador de espera de evento de forma manual o automática. La EventWaitHandle clase puede representar un identificador de espera de eventos local (evento local) o un identificador de espera de eventos del sistema con nombre (evento o evento del sistema, visible para todos los procesos).
Nota:
Los identificadores de espera de evento no son eventos de .NET. No hay delegados ni controladores de eventos implicados. La palabra "event" se usa para describirlos porque tradicionalmente se les conoce como eventos del sistema operativo y, debido a que el acto de señalar el identificador de espera indica a los subprocesos en espera que se ha producido un evento.
Ambos identificadores de espera de evento local y con nombre usan objetos de sincronización del sistema, protegidos por contenedores SafeWaitHandle para garantizar la liberación de los recursos. Puede usar el Dispose método para liberar los recursos inmediatamente cuando haya terminado de usar el objeto .
Identificadores de espera de evento que se restablecen automáticamente
Para crear un evento de restablecimiento automático, especifique EventResetMode.AutoReset al crear el EventWaitHandle objeto . Como sugiere su nombre, este evento de sincronización se restablece automáticamente cuando recibe la señal, después de liberar un único hilo en espera. Indique el evento llamando a su método Set.
Normalmente, los eventos de restablecimiento automático se usan para proporcionar acceso exclusivo a un recurso para un único subproceso a la vez. Un subproceso solicita el recurso llamando al método WaitOne. Si ningún otro subproceso contiene el identificador de espera, el método devuelve true y el subproceso que realiza la llamada tiene el control del recurso.
Importante
Al igual que con todos los mecanismos de sincronización, debe asegurarse de que todas las rutas de acceso de código esperen al identificador de espera adecuado antes de obtener acceso a un recurso protegido. La sincronización de subprocesos es cooperativa.
Si un evento de restablecimiento automático se señaliza cuando no hay ningún subproceso en espera, permanece señalado hasta que un subproceso intenta esperar en él. El evento libera el hilo y se restablece inmediatamente, bloqueando hilos posteriores.
Identificadores de espera de evento que se restablecen manualmente
Para crear un evento de restablecimiento manual, especifique EventResetMode.ManualReset al crear el EventWaitHandle objeto . Como su nombre implica, este evento de sincronización debe restablecerse manualmente después de que se haya señalado. Hasta que se restablezca, mediante una llamada a su método Reset, los subprocesos que esperan en el identificador de evento se ejecutarán inmediatamente, sin bloquearse.
Un evento de reinicio manual actúa como la puerta de un corral. Si no se señala un evento, los subprocesos que esperan en él se bloquean, como los caballos de un establo. Cuando se señala el evento, mediante una llamada a su método Set, todos los subprocesos en espera pueden continuar libremente. El evento permanece señalado hasta que se llama a su método Reset. Esto hace que el evento de restablecimiento manual sea una manera ideal de mantener los subprocesos que necesitan esperar hasta que un subproceso finalice una tarea.
Al igual que los caballos que salen de un corral, el sistema operativo tarda tiempo en programar los subprocesos liberados y reanudar la ejecución. Si se llama al Reset método antes de que todos los subprocesos hayan reanudado la ejecución, los subprocesos restantes se vuelven a bloquear. Qué subprocesos se reanudan y qué subprocesos bloquean depende de factores aleatorios, como la carga en el sistema, el número de subprocesos que esperan al programador, etc. Esto no es un problema si el subproceso que señala el evento finaliza después de la señalización, que es el patrón de uso más común. Si desea que el subproceso que señaló el evento inicie una nueva tarea después de que se hayan reanudado todos los subprocesos en espera, debe bloquearlo hasta que todos los subprocesos en espera se hayan reanudado. En caso contrario, se produce una condición de carrera y el comportamiento del código es imprevisible.
Características comunes a eventos automáticos y manuales
Normalmente, uno o varios subprocesos se bloquean en un EventWaitHandle hasta que un subproceso desbloqueado llama al método Set, que libera uno de los hilos en espera (en el caso de eventos de restablecimiento automático) o todos ellos (en el caso de eventos de restablecimiento manual). Un subproceso puede señalar EventWaitHandle y, a continuación, bloquearse ahí, como una operación atómica, mediante una llamada al método estático WaitHandle.SignalAndWait.
EventWaitHandle Los objetos se pueden usar con los métodos estáticos WaitHandle.WaitAll y WaitHandle.WaitAny . Dado que las EventWaitHandle clases y Mutex derivan de WaitHandle, puede usar ambas clases con estos métodos.
Eventos con nombre
El sistema operativo Windows permite que los identificadores de espera de eventos tengan nombres. Un evento con nombre abarca todo el sistema. Es decir, una vez creado el evento con nombre, es visible para todos los subprocesos de todos los procesos. Por lo tanto, los eventos con nombre pueden utilizarse para sincronizar tanto las actividades de procesos como las de subprocesos.
Puede crear un EventWaitHandle objeto que represente un evento del sistema con nombre mediante uno de los constructores que especifica un nombre de evento.
Nota:
Dado que los eventos con nombre son de todo el sistema, es posible tener varios EventWaitHandle objetos que representen el mismo evento con nombre. Cada vez que se llama a un constructor o al OpenExisting método , se crea un nuevo EventWaitHandle objeto. Al especificar el mismo nombre repetidamente se crean varios objetos que representan el mismo evento con nombre.
Se recomienda tener precaución en el uso de eventos nombrados. Dado que son de todo el sistema, otro proceso que usa el mismo nombre puede bloquear tus hilos inesperadamente. El código malintencionado que se ejecuta en el mismo equipo podría usarlo como base de un ataque por denegación de servicio.
Use la seguridad del control de acceso para proteger un EventWaitHandle objeto que representa un evento con nombre, preferiblemente mediante un constructor que especifique un EventWaitHandleSecurity objeto. También puede aplicar la seguridad del control de acceso mediante el método SetAccessControl, pero esto deja una ventana de vulnerabilidad entre el momento en que se crea el identificador de espera de eventos y el momento en que está protegido. Proteger los eventos con seguridad de control de acceso ayuda a evitar ataques malintencionados, pero no soluciona el problema de conflictos involuntarios de nombres.
Nota:
A diferencia de la EventWaitHandle clase , las clases derivadas AutoResetEvent y ManualResetEvent solo pueden representar identificadores de espera locales. No pueden representar eventos de sistema con nombre.