Tengo un número de subprocesos que esperan en un evento, realizan alguna acción, luego esperan en el evento nuevamente. Otro hilo activará el evento cuando sea apropiado.Python threading.Event() - Asegurando que todos los subprocesos en espera se activen en event.set()
No puedo encontrar la forma de garantizar que cada hebra en espera se active exactamente una vez sobre el evento que se está configurando. Actualmente tengo el hilo desencadenante configurado, dormir un poco, luego despejarlo. Desafortunadamente, esto lleva a que los hilos de espera agarren el evento establecido muchas veces, o ninguno.
No puedo simplemente hacer que el hilo desencadenante engendre los subprocesos de respuesta para ejecutarlos una vez porque son respuestas a solicitudes realizadas desde otros lugares.
En resumen: en Python, ¿cómo puedo hacer que un hilo establezca un evento y asegurar que cada hilo en espera actúa sobre el evento exactamente una vez antes de que se borre?
Actualización:
He intentado configurarlo usando una cerradura y una cola, pero no funciona. Aquí es lo que tengo:
# Globals - used to synch threads
waitingOnEvent = Queue.Queue
MainEvent = threading.Event()
MainEvent.clear() # Not sure this is necessary, but figured I'd be safe
mainLock = threading.Lock()
def waitCall():
mainLock.acquire()
waitingOnEvent.put("waiting")
mainLock.release()
MainEvent.wait()
waitingOnEvent.get(False)
waitingOnEvent.task_done()
#do stuff
return
def triggerCall():
mainLock.acquire()
itemsinq = waitingOnEvent.qsize()
MainEvent.set()
waitingOnEvent.join()
MainEvent.clear()
mainLock.release()
return
La primera vez, itemsinq refleja correctamente el número de llamadas están a la espera, pero sólo el primer hilo de espera para realizar la llamada va a salir adelante. Desde entonces, itemsinq siempre es 1, y los hilos de espera se turnan; cada vez que ocurre la llamada de activación, la siguiente pasa.
Actualización 2 Parece como si sólo una de la event.wait() hilos está despertando
, y sin embargo el queue.join) está trabajando (. Esto me sugiere que un hilo de espera se despierta, toma de la cola y llama a task_done(), y que get()/task_done() solo vacía la cola y permite el join(). El hilo desencadenante luego completa el join(), borra el evento y así evita que los otros hilos en espera pasen. Sin embargo, ¿por qué la cola se registraría como vacía/terminada después de una sola llamada get/task_done?
Parece que solo uno está despertando, incluso si hago un comentario en queue.get() y queue.task_done() y cuelgo el desencadenador para que no pueda despejar el evento.
Esto suena como un posible defecto de diseño, probablemente haya una mejor manera de lograr lo que está tratando de lograr. ¿Puedes publicar más detalles sobre lo que se supone que deben hacer los hilos? –