He leído la documentación sobre esto y creo que lo entiendo. Un se AutoResetEvent
restablece cuando pasa el código event.WaitOne()
, pero ManualResetEvent
no lo hace.
¿Es esto correcto?
c#
.net
multithreading
autoresetevent
manualresetevent
Ben McNiel
fuente
fuente
Respuestas:
Si. Es como la diferencia entre un peaje y una puerta. Esta
ManualResetEvent
es la puerta, que debe cerrarse (reiniciarse) manualmente. ElAutoResetEvent
es una cabina de peaje, lo que permite un coche a pasar y cerrar automáticamente antes de que el siguiente puede pasar.fuente
Solo imagine que se
AutoResetEvent
ejecutaWaitOne()
yReset()
como una sola operación atómica.fuente
La respuesta corta es sí. La diferencia más importante es que un AutoResetEvent solo permitirá que continúe un solo hilo de espera. Un ManualResetEvent, por otro lado, seguirá permitiendo que los subprocesos, varios al mismo tiempo, continúen hasta que le pidas que se detenga (Restablezca).
fuente
Enhebrado en C # - Libro electrónico gratuito
Un ManualResetEvent es una variación de AutoResetEvent. Se diferencia en que no se restablece automáticamente después de que se deja pasar un hilo en una llamada WaitOne, y por lo tanto funciona como una puerta: al llamar a Set se abre la puerta, permitiendo cualquier cantidad de hilos por los que pasa WaitOne en la puerta; Al llamar a Reset, se cierra la puerta y, potencialmente, se acumula una cola de camareros hasta que se abre de nuevo.
Se podría simular esta funcionalidad con un campo booleano "gateOpen" (declarado con la palabra clave volátil) en combinación con "spin-sleeping", verificando repetidamente la bandera y luego durmiendo durante un corto período de tiempo.
En ocasiones, ManualResetEvents se usa para indicar que una operación en particular está completa o que la inicialización de un subproceso está lista y lista para realizar el trabajo.
fuente
He creado sencillos ejemplos para aclarar la comprensión de
ManualResetEvent
frenteAutoResetEvent
.AutoResetEvent
: supongamos que tiene 3 hilos de trabajo. Si alguno de esos hilos llamará aWaitOne()
los otros 2 hilos, detendrá la ejecución y esperará la señal. Estoy asumiendo que están usandoWaitOne()
. Es como; Si no trabajo, nadie trabaja. En el primer ejemplo puedes ver queCuando llame,
Set()
todos los hilos funcionarán y esperarán la señal. Después de 1 segundo, estoy enviando una segunda señal y se ejecutan y esperan (WaitOne()
). Piensa que estos muchachos son jugadores del equipo de fútbol y si un jugador dice que esperaré hasta que el gerente me llame, y otros esperarán hasta que el gerente les diga que continúen (Set()
)En este ejemplo, puede ver claramente que cuando golpea por primera
Set()
vez, dejará ir todos los hilos, ¡luego de 1 segundo le indicará a todos los hilos que esperen! Tan pronto como los configure de nuevo, independientemente de queWaitOne()
llamen dentro, seguirán ejecutándose porque debe llamar manualmenteReset()
para detenerlos a todos.Se trata más de la relación Árbitro / Jugadores allí, independientemente de si alguno de los jugadores está lesionado y esperar a que otros continúen trabajando. Si el Árbitro dice esperar (
Reset()
), todos los jugadores esperarán hasta la próxima señal.fuente
autoResetEvent.WaitOne()
es parecido a
como una operación atómica
fuente
OK, normalmente no es una buena práctica agregar 2 respuestas en el mismo hilo, pero no quería editar / eliminar mi respuesta anterior, ya que puede ayudar de otra manera.
Ahora, he creado, a continuación, un fragmento de aplicación de consola mucho más completo y fácil de entender.
Simplemente ejecute los ejemplos en dos consolas diferentes y observe el comportamiento. Tendrás una idea mucho más clara de lo que está sucediendo detrás de escena.
Evento de reinicio manual
Evento de reinicio automático
fuente
AutoResetEvent mantiene una variable booleana en la memoria. Si la variable booleana es falsa, entonces bloquea el hilo y si la variable booleana es verdadera, desbloquea el hilo.
Cuando instanciamos un objeto AutoResetEvent, pasamos el valor predeterminado del valor booleano en el constructor. A continuación se muestra la sintaxis de instanciar un objeto AutoResetEvent.
Método WaitOne
Este método bloquea el hilo actual y espera la señal de otro hilo. El método WaitOne coloca el subproceso actual en un estado de subproceso de suspensión. El método WaitOne devuelve verdadero si recibe la señal; de lo contrario, devuelve falso.
La segunda sobrecarga del método WaitOne espera el número de segundos especificado. Si no recibe ningún hilo de señal, continúa su trabajo.
Llamamos al método WaitOne pasando los 2 segundos como argumentos. En el ciclo while, espera la señal durante 2 segundos y luego continúa su trabajo. Cuando el hilo recibió la señal, WaitOne regresa verdadero y sale del bucle e imprime el "Hilo tiene señal".
Establecer método
El método AutoResetEvent Set envió la señal al subproceso en espera para continuar su trabajo. A continuación se muestra la sintaxis de llamar al método Set.
ManualResetEvent mantiene una variable booleana en la memoria. Cuando la variable booleana es falsa, bloquea todos los hilos y cuando la variable booleana es verdadera, desbloquea todos los hilos.
Cuando instanciamos un ManualResetEvent, lo inicializamos con un valor booleano predeterminado.
En el código anterior, inicializamos el ManualResetEvent con un valor falso, lo que significa que todos los hilos que llaman al método WaitOne se bloquearán hasta que algún hilo llame al método Set ().
Si inicializamos ManualResetEvent con valor verdadero, todos los hilos que llaman al método WaitOne no se bloquearán y podrán continuar.
Método WaitOne
Este método bloquea el hilo actual y espera la señal de otro hilo. Devuelve verdadero si recibe una señal; de lo contrario, devuelve falso.
A continuación se muestra la sintaxis de llamar al método WaitOne.
En la segunda sobrecarga del método WaitOne, podemos especificar el intervalo de tiempo hasta que el hilo actual espere la señal. Si dentro del tiempo interno, no recibe una señal, devuelve falso y pasa a la siguiente línea de método.
A continuación se muestra la sintaxis de llamar al método WaitOne con intervalo de tiempo.
Hemos especificado 5 segundos en el método WaitOne. Si el objeto manualResetEvent no recibe una señal entre 5 segundos, establece la variable isSignalled en false.
Establecer método
Este método se utiliza para enviar la señal a todos los hilos en espera. El método Set () establece la variable booleana del objeto ManualResetEvent en true. Todos los hilos en espera se desbloquean y continúan.
A continuación se muestra la sintaxis de llamar al método Set ().
Método de reinicio
Una vez que llamamos al método Set () en el objeto ManualResetEvent, su valor booleano permanece verdadero. Para restablecer el valor podemos usar el método Reset (). El método de reinicio cambia el valor booleano a falso.
A continuación se muestra la sintaxis de llamar al método Reset.
Debemos llamar inmediatamente al método Reset después de llamar al método Set si queremos enviar la señal a los hilos varias veces.
fuente
Si. Esto es absolutamente correcto.
Puede ver ManualResetEvent como una forma de indicar el estado. Algo está encendido (Set) o apagado (Reset). Una ocurrencia con cierta duración. Cualquier subproceso que espere que ocurra ese estado puede continuar.
Un AutoResetEvent es más comparable a una señal. Una indicación de un disparo de que algo ha sucedido. Una ocurrencia sin ninguna duración. Por lo general, pero no necesariamente, el "algo" que ha sucedido es pequeño y debe ser manejado por un solo subproceso, de ahí el restablecimiento automático después de que un solo subproceso haya consumido el evento.
fuente
Si, eso es correcto.
Puede hacerse una idea mediante el uso de estos dos.
Si necesita saber que ha terminado con algún trabajo y otros (subprocesos) esperando que esto pueda continuar, debe usar ManualResetEvent.
Si necesita tener acceso exclusivo mutuo a cualquier recurso, debe usar AutoResetEvent.
fuente
Si desea comprender AutoResetEvent y ManualResetEvent, debe comprender no enhebrar sino interrumpir.
.NET quiere conjurar programación de bajo nivel lo más distante posible.
Una interrupción es algo que se usa en la programación de bajo nivel que equivale a una señal que desde baja se volvió alta (o viceversa). Cuando esto sucede, el programa interrumpe su ejecución normal y mueve el puntero de ejecución a la función que maneja este evento .
Lo primero que debe hacer cuando ocurre una interrupción es restablecer su estado, ya que el hardware funciona de esta manera:
Esta es la diferencia entre ManualResetEvent y AutoResetEvent.
Si sucede un ManualResetEvent y no lo reinicio, la próxima vez que ocurra no podré escucharlo.
fuente