Pregunta

Tengo un hilo que escribe los resultados en una cola.

En otro hilo (GUI), periódicamente (en el evento IDLE) verifico si hay resultados en la cola, como este:

def queue_get_all(q):
    items = []
    while 1:
        try:
            items.append(q.get_nowait())
        except Empty, e:
            break
    return items

¿Es esta una buena manera de hacerlo?

Editar:

  

Lo pregunto porque a veces la   hilo de espera se queda atascado por unos pocos   segundos sin sacar nuevo   resultados.

El " pegado " El problema se debió a que estaba haciendo el procesamiento en el controlador de eventos inactivo, sin asegurarme de que dichos eventos se generan realmente llamando a wx.WakeUpIdle , como se recomienda.

¿Fue útil?

Solución

Me sorprendería mucho si la llamada get_nowait () causó la pausa al no regresar si la lista estaba vacía.

¿Podría ser que está publicando una gran cantidad de elementos (¿tal vez grandes?) entre las comprobaciones, lo que significa que el hilo receptor tiene una gran cantidad de datos para extraer de la Queue ? Puede intentar limitar el número que recupera en un lote:

def queue_get_all(q):
    items = []
    maxItemsToRetreive = 10
    for numOfItemsRetrieved in range(0, maxItemsToRetreive):
        try:
            if numOfItemsRetrieved == maxItemsToRetreive:
                break
            items.append(q.get_nowait())
        except Empty, e:
            break
    return items

Esto limitaría el hilo receptor a extraer hasta 10 elementos a la vez.

Otros consejos

Si siempre está sacando todos los elementos disponibles de la cola, ¿hay algún punto real en el uso de una cola, en lugar de solo una lista con un bloqueo? es decir:

from __future__ import with_statement
import threading

class ItemStore(object):
    def __init__(self):
        self.lock = threading.Lock()
        self.items = []

    def add(self, item):
        with self.lock:
            self.items.append(item)

    def getAll(self):
        with self.lock:
            items, self.items = self.items, []
        return items

Si también los está extrayendo individualmente y haciendo uso del comportamiento de bloqueo para las colas vacías, entonces debe usar la Cola, pero su caso de uso parece mucho más simple y podría ser mejor atendido por el enfoque anterior.

[Edit2] me perdí el hecho de que estás sondeando la cola desde un bucle inactivo, y desde tu actualización, veo que el problema no está relacionado con la contención, por lo que el El siguiente enfoque no es realmente relevante para su problema. Lo he dejado en caso de que alguien encuentre útil una variante de bloqueo de esto:

Para los casos en los que desea bloquear hasta que obtenga al menos un resultado, puede modificar el código anterior para esperar a que los datos estén disponibles mediante la señalización del hilo productor. Ej.

class ItemStore(object):
    def __init__(self):
        self.cond = threading.Condition()
        self.items = []

    def add(self, item):
        with self.cond:
            self.items.append(item)
            self.cond.notify() # Wake 1 thread waiting on cond (if any)

    def getAll(self, blocking=False):
        with self.cond:
            # If blocking is true, always return at least 1 item
            while blocking and len(self.items) == 0:
                self.cond.wait()
            items, self.items = self.items, []
        return items

Creo que la forma más sencilla de eliminar todos los elementos de la cola es la siguiente:

def get_all_queue_result(queue):

    result_list = []
    while not queue.empty():
        result_list.append(queue.get())

    return result_list

Veo que está usando get_nowait () que, de acuerdo con la documentación, " devuelve [s] un elemento si está disponible de inmediato, de lo contrario, genere la excepción Vacío "

Ahora, puedes salir del bucle cuando se lanza una excepción vacía. Por lo tanto, si no hay ningún resultado disponible inmediatamente en la cola, su función devuelve una lista de elementos vacía.

¿Hay alguna razón por la que no esté utilizando el método get () en su lugar? Puede darse el caso de que get_nowait () falle porque la cola está atendiendo una solicitud put () en ese mismo momento.

Si ha terminado de escribir en la cola, qsize debería hacer el truco sin necesidad de revisar la cola para cada iteración.

responseList = []
for items in range(0, q.qsize()):
    responseList.append(q.get_nowait())

El método más simple es usar una lista de comprensión:

items = [q.get() for _ in range(q.qsize())]
El uso de

range generalmente está mal visto, pero aún no he encontrado un método más simple.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top