.net - que - ¿Cuándo usaría AutoResetEvent y ManualResetEvent en lugar de Monitor.Wait()/Monitor.Pulse()?
synchronized c# (4)
Ambos parecen cumplir el mismo propósito. ¿Cuándo elegiría uno sobre el otro?
Este tutorial tiene descripciones detalladas de lo que debe saber: http://www.albahari.com/threading/
En particular, esto cubrirá las clases XXXResetEvent,
http://www.albahari.com/threading/part2.aspx
y esto cubrirá Wait / Pulse: http://www.albahari.com/threading/part4.aspx#_Wait_and_Pulse
Utilice los eventos cuando tenga un hilo que está esperando en uno o todos los eventos para hacer algo.
Use el monitor si desea restringir el acceso a una estructura de datos limitando la cantidad de subprocesos que pueden acceder a ella.
Los monitores generalmente protegen un recurso, mientras que los eventos indican que algo está sucediendo, como la desactivación de la aplicación.
Además, los eventos se pueden nombrar (ver el método OpenExisting), esto les permite ser utilizados para la sincronización en diferentes procesos.
En mi opinión, es mejor usar Monitor si puede, Monitor.Wait y Monitor.Pulse / PulseAll se utilizan para señalizar entre subprocesos (como Manual / AutoResetEvent) sin embargo, Monitor es más rápido y no utiliza un recurso de sistema nativo. También aparentemente, Monitor se implementa en el modo de usuario y se gestiona, mientras que Manual / AutoResetEvents requiere cambiar al modo kernel e invocar a las llamadas nativas win32 que usan un identificador de espera.
Hay situaciones en las que necesitaría usar Manual / AutoResetEvent, por ejemplo, para señalar entre procesos, puede usar eventos con nombre, y supongo que señalará hilos nativos en su aplicación.
Estoy regurgitando lo que he leído en este excelente artículo sobre enhebrar.
Vale la pena leer todo el artículo, sin embargo, el enlace lo lleva a la sección de manejo de espera que detalla los eventos y supervisa la espera / pulso.
Utilizaría un WaitHandle
cuando desee que un hilo envíe o reciba una señal binaria sin la necesidad de una sección crítica. Monitor.Wait
y Monitor.Pulse
por otro lado requieren una sección crítica. Al igual que la mayoría de los mecanismos de sincronización en el BCL, hay cierta superposición en cómo se pueden usar los dos que mencionaste. Pero, no piense por un momento que cumplen el mismo propósito.
Monitor.Wait
y Monitor.Pulse
son un mecanismo de sincronización mucho más primitivo que un MRE o ARE. De hecho, puedes construir un MRE o ARE usando nada más que la clase Monitor
. El concepto más importante de entender es cómo difieren los métodos Monitor.Wait
y WaitHandle.WaitOne
. Wait
y WaitOne
colocarán el hilo en el estado WaitSleepJoin
, lo que significa que el hilo queda inactivo y solo responde a un Thread.Interrupt
o a la respectiva llamada Pulse
o Set
. Pero, y esta es una gran diferencia, Wait
abandonará una sección crítica y la volverá a adquirir de forma atómica . WaitOne
simplemente no puede hacer esto. Es una diferencia tan fundamental en la forma en que se comportan estos mecanismos de sincronización que define los escenarios en los que se pueden usar.
En la mayoría de las situaciones, elegirías un MRE o ARE. Estos satisfacen la mayoría de las situaciones donde un hilo necesita recibir una señal de otro. Sin embargo, si desea crear su propio mecanismo de señalización, deberá usar Wait
y Pulse
. Pero, una vez más, .NET BCL ya tiene cubiertos la mayoría de los mecanismos de señalización populares. Los siguientes mecanismos de señalización ya existen 1 .
- ManualResetEvent (o ManualResetEventSlim)
- AutoResetEvent
- Semaphore (o SemaphoreSlim)
- EventWaitHandle
- CountdownEvent
- Barrera
1 Una mención honorífica va a la clase BlockingCollection
. No es un mecanismo de señalización per se, pero tiene las cualidades de un mecanismo de señalización con el beneficio adicional de que puede adjuntar datos a la señal. En este caso, la señal significa que un elemento está disponible en la colección y los datos asociados con esa señal es el elemento mismo.