¿Cuál es el concepto básico detrás de WaitHandle
en C# .net threading? ¿Cuál es su uso? ¿Cuándo usarlo? ¿Cuál es el uso de WaitAll y WaitAny métodos dentro de él?¿Cuál es el concepto básico detrás de WaitHandle?
Respuesta
Siempre que desee controlar la ejecución de varios subprocesos en su aplicación. Aunque esto no solo significa que solo un hilo incrementa el contador; pero deje que los hilos comiencen/detengan o pause sobre un evento.
Ver WaitHandles - Auto/ManualResetEvent and Mutex
--EDIT--
WaitHandle
s son el mecanismoque "utiliza" para controlar la ejecución de los hilos. No se trata de identificadores que no sean accesibles dentro de un hilo; se trata de usarlos dentro del hilo.
Esto puede ser un ejemplo gordo, pero por favor tengan paciencia conmigo; Piense, una dama le da cinco silbatos diferentes a cinco niñas y les dice que suene cada vez que ocurra something
; el proceso es para que cada niña pite un silbato, y la dama sabría quién hizo sonar el silbato.
Ahora, no se trata de compartir los silbidos unos con otros, se trata, probablemente, de que la dama los use para "controlar" la ejecución o el proceso de cómo las niñas pitan el silbato.
Por lo tanto, técnicamente, el proceso sería:
- crear un evento de espera (ManualResetEvent objeto)
- registrar los eventos,
WaitHandle.WaitAny(events);
- Después de que haya terminado la operación se realiza en el hilo, el
.Set()
, lo que le diría al WaitHandle que '¡ya terminé!'.
Por ejemplo, considere el ejemplo del enlace proporcionado. He agregado los pasos para que entiendas la lógica. Estos no son los pasos codificados, pero solo para que pueda entender.
class Test
{
static void Main()
{
//STEP 1: Create a wait handle
ManualResetEvent[] events = new ManualResetEvent[10];//Create a wait handle
for (int i=0; i < events.Length; i++)
{
events[i] = new ManualResetEvent(false);
Runner r = new Runner(events[i], i);
new Thread(new ThreadStart(r.Run)).Start();
}
//STEP 2: Register for the events to wait for
int index = WaitHandle.WaitAny(events); //wait here for any event and print following line.
Console.WriteLine ("***** The winner is {0} *****",
index);
WaitHandle.WaitAll(events); //Wait for all of the threads to finish, that is, to call their cooresponding `.Set()` method.
Console.WriteLine ("All finished!");
}
}
class Runner
{
static readonly object rngLock = new object();
static Random rng = new Random();
ManualResetEvent ev;
int id;
internal Runner (ManualResetEvent ev, int id)
{
this.ev = ev;//Wait handle associated to each object, thread in this case.
this.id = id;
}
internal void Run()
{
//STEP 3: Do some work
for (int i=0; i < 10; i++)
{
int sleepTime;
// Not sure about the thread safety of Random...
lock (rngLock)
{
sleepTime = rng.Next(2000);
}
Thread.Sleep(sleepTime);
Console.WriteLine ("Runner {0} at stage {1}",
id, i);
}
//STEP 4: Im done!
ev.Set();
}
}
La idea detrás de los métodos WaitAll y WaitAny es que son útiles cuando tiene muchas tareas que desea ejecutar en paralelo.
Por ejemplo, supongamos que tiene que realizar un trabajo que requiere que procese un poco los 1000 elementos de una matriz que deben procesarse en paralelo. Un típico Core 2 Duo + hyperthreading solo tiene 4 procesadores lógicos, por lo que no tiene mucho sentido tener más de 4 hilos al mismo tiempo (en realidad, sí, pero eso es una historia para otro momento, lo haremos pretender y usar el modelo simple de "un hilo por procesador" por ahora). Entonces 4 hilos, pero 1000 artículos; ¿qué haces?
Una opción es utilizar el método WaitAny. Lanzas 4 hilos, y cada vez que el método WaitAny regresa, comienzas otro, hasta que todos los 1000 elementos estén en cola. Tenga en cuenta que este es un ejemplo pobre para WaitAny, ya que también podría dividir su matriz en 250 bloques de elementos. Sin embargo, con suerte, te da una idea del tipo de situación en la que WaitAny es útil. Hay otras situaciones similares en las que WaitAny puede tener mucho sentido.
Pero ahora volvamos al escenario con 4 hilos que procesan 250 elementos de su matriz de 1000 elementos. Con esta opción, puede usar el método WaitAll para esperar a que finalice todo el procesamiento.
Es una clase abstracta, no la usa directamente. Las clases derivadas de hormigón son ManualResetEvent, AutoResetEvent, Mutex y Semaphore. Clases importantes en su caja de herramientas para implementar la sincronización de subprocesos. Heredan los métodos WaitOne, WaitAll y WaitAny, los usa para detectar que uno o más hilos señalaron la condición de espera.
El escenario de uso típico para Manual/AutoResetEvent es indicarle a un hilo que salga o dejar que un hilo indique que ha progresado a un punto de secuencia importante. Semaphore te ayuda a limitar el número de hilos que realizan una acción. O para implementar la sincronización de subprocesos que no debe tener afinidad con un hilo en particular. Mutex está ahí para asignar la propiedad a una sección de código a un hilo, la instrucción de bloqueo a menudo se aplica allí también.
Se han escrito libros sobre él. Joe Duffy's Concurrent Programming in Windows es lo último y lo mejor. Muy recomendable si piensas escribir código enhebrado.
WaitHandle
es una clase base abstracta para los dos identificadores de eventos comúnmente utilizados: AutoResetEvent
y ManualResetEvent
.
Ambas clases permiten que un hilo "señalice" uno o más hilos. Se usan para sincronizar (o serializar la actividad) entre hilos. Esto se logra utilizando los métodos Set
y WaitOne
(o WaitAll
). Por ejemplo:
Tema 1:
// do setup work
myWaitHandle.Set();
Tema 2:
// do setup work
myWaitHandle.WaitOne();
// this code will not continue until after the call to `Set`
// in thread 1 completes.
Este es un ejemplo muy rudimentario, y hay un montón de ellos disponibles en la web.La idea básica es que WaitOne
se usa para esperar una señal de otro hilo que indique que algo ha sucedido. En el caso de AsyncWaitHandle
(que se devuelve al invocar un delegado de forma asíncrona), WaitOne
le permite hacer que el subproceso actual espere hasta que se complete la operación asincrónica.
Cuando AutoResetEvent
o ManualResetEvent
no están configurados, las llamadas a WaitOne
bloquearán el hilo de llamada hasta que se llame al Set
. Estas dos clases se diferencian solo en que AutoResetEvent
"desactiva" el evento una vez que se completa una llamada exitosa a WaitOne
, haciendo que las llamadas subsiguientes se bloqueen nuevamente hasta que se llame al Set
. ManualResetEvent
debe ser "desarmado" explícitamente llamando al Reset
.
WaitAll
y WaitAny
son métodos estáticos en la clase WaitHandle
que le permiten especificar una serie de WaitHandles
que esperar en. WaitAll
bloqueará hasta todos de los identificadores provistos son Set
, mientras que WaitAny
solo bloqueará hasta uno de ellos obtiene Set
.
Aquí hay algunas respuestas muy largas.Para cualquiera que busque la respuesta corta:
Wait handle es un mecanismo para hacer que un hilo espere hasta que otro hilo llegue a cierto punto.
También puede tener varios hilos en espera y/o varios hilos que se están esperando, de ahí los métodos WaitOne
, WaitAll
y WaitAny
. También hay varias opciones de semántica disponibles al elegir una de estas clases: Mutex
, Semaphore
, ManualResetEvent
, AutoResetEvent
que están bien documentadas.
- 1. ¿Cuál es el concepto detrás de R.java?
- 2. ¿Cuál es el concepto detrás de la compresión zip?
- 3. ¿Cuál es el concepto general detrás de XSS?
- 4. ¿cuál es el uso básico de alignment_storage?
- 5. ¿Cuál es el algoritmo detrás de sleep()?
- 6. ¿Cuál es el concepto de una Asamblea en .NET?
- 7. ¿Cuál es el concepto de "conformidad débil" en Scala?
- 8. ¿Cuál es el concepto de carril en YouTrack?
- 9. ¿Cuál es la magia detrás de Lightstreamer?
- 10. ¿Cuál es el algoritmo detrás de la generación de buscaminas
- 11. ¿Cuál es el razonamiento de diseño detrás de HandleScope?
- 12. ¿Cuál es el razonamiento detrás de los encabezados?
- 13. ¿Cuál es el mecanismo detrás de startActivityForResult() en Android?
- 14. ¿Cuál es el código detrás de datagridtemplatecolumn, y cómo usarlo?
- 15. Comprender el concepto de Inodes
- 16. ¿Es el hilo un concepto de Windows?
- 17. ¿Cuál es el razonamiento detrás del contexto zeroMQ?
- 18. ¿Cuál es el razonamiento detrás del encabezado HTTP Date?
- 19. Cancelación con WaitHandle
- 20. Cuál es la matemática detrás de la rueda de colores
- 21. ¿Cuál es la tecnología detrás de Windows Azure REST Api?
- 22. ¿Cuál es la razón detrás de Object.clone() está protegido
- 23. ANDROID: ¿Cuál es la idea principal detrás de usar strings.xml?
- 24. ¿Cuál es la idea detrás de 'mango GC Fijado'?
- 25. ¿Cuál es el concepto de * rol de trabajador * en la nube de Windows Azure?
- 26. ¿Cuál es la razón detrás de cbegin/cend?
- 27. ¿Cuál es el significado del concepto de "unidad de trabajo" en NHibernate y otros ORM?
- 28. ¿Cuál es el concepto de intención pendiente? ¿Por qué y cuándo usamos intención pendiente?
- 29. Obteniendo el concepto de Git de "etapa"
- 30. ¿Cuál es la concepción detrás: Tipo - Elemento - Espejo
WaitAll() - se utiliza para esperar a que todos los identificadores de un conjunto estén libres/señalizados ... ¿Significa que Handles no estará accesible para otros subprocesos hasta que no sean liberados (otros hilos deberían esperar para estas manijas en el conjunto)? – DotNetBeginner
@DotNetBeginner: '¿Significa que Handles no será accesible para otros hilos'; por favor vea mi publicación actualizada, un ejemplo agregado solo para responder a esta pregunta. –
Vale la pena decir que 'ev.Set()' mejor para poner en el bloque 'finally' –