Frage

Ich habe einen Thread, die Ergebnisse in eine Warteschlange schreibt.

In einem anderen Thread (GUI), I periodisch (im IDLE-Ereignisse) prüfen, ob es Ergebnisse in der Warteschlange sind, wie folgt:

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

Ist das ein guter Weg, es zu tun?

Edit:

  

Ich frage, weil manchmal die   Warten Thread wird für ein paar stecken   Sekunden ohne Entnahme neu   Ergebnisse.

Das „steckt“ Problem entpuppte, weil ich die Verarbeitung im Leerlauf Ereignishandler tat, ohne sicherzustellen, dass solche Ereignisse durch tatsächlich erzeugt fordern wx.WakeUpIdle, wie empfohlen.

War es hilfreich?

Lösung

Ich wäre sehr überrascht, wenn der get_nowait() Aufruf der Pause durch nicht wiederkehr verursacht, wenn die Liste leer war.

Könnte es sein, dass Sie eine große Anzahl von (vielleicht groß?) Sind Buchungspositionen zwischen den Prüfungen, die bedeutet, dass das Aufnahmegewinde eine große Menge an Daten hat aus dem Queue zu ziehen? Sie könnten versuchen, die Nummer, die Sie in einer Charge Begrenzung abrufen:

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

Dies würde begrenzt die Aufnahme Thread zu einem Zeitpunkt zu 10 Elementen nach oben ziehen.

Andere Tipps

Wenn Sie immer alle verfügbaren Elemente aus der Warteschlange ziehen, gibt es einen echten Punkt eine Warteschlange in, anstatt nur eine Liste mit einem Schloss? dh:

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

Wenn Sie auch einzeln ziehen, und die Nutzung des Sperrverhaltens für leere Warteschlangen, dann sollten Sie Queue, aber Ihr Anwendungsfall sieht viel einfacher und besser durch den obigen Ansatz bedient werden könnte.

[Edit2] ich die Tatsache übersehen hatte, dass Sie Abfrage der Warteschlange aus einer Warteschleife sind, und von Ihrem Update, ich sehe, dass das Problem nicht auf Konkurrenz verwandt ist, so dass die unten Ansatz ist, um Ihr Problem nicht wirklich relevant. Ich habe es nach links in falls jemand findet eine blockierende Variante dieses nützlich:

Für die Fälle, wo Sie wollen, zu blockieren, bis zumindest ein Ergebnis erhalten, können Sie den obigen Code ändern zu warten, Daten zu werden durch vom Hersteller Thread signalisiert wird. ZB.

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

Ich denke, der einfachste Weg, um alle Elemente des Erhaltens aus der Warteschlange ist die folgende:

def get_all_queue_result(queue):

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

    return result_list

Ich sehe, Sie verwenden get_nowait (), die entsprechend der Dokumentation „return [s] ein Element, wenn man sofort verfügbar ist, sonst die Leere Ausnahme auslösen“

Nun, passieren Sie aus der Schleife zu brechen, wenn eine Leere Ausnahme ausgelöst. Wenn es also kein Ergebnis sofort verfügbar in der Warteschlange befindet, Ihre Funktion gibt eine leere Positionsliste.

Gibt es einen Grund, warum Sie nicht die get () verwenden Methode statt? Es kann der Fall sein, dass die get_nowait () schlägt fehl, weil die Warteschlange bis zum gleichen Zeitpunkt eine Put () Anforderung bedient.

Wenn Sie in die Warteschlange fertig sind schreiben, sollte WGröße den Trick tun, ohne dass die Warteschlange für jede Iteration zu überprüfen.

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

Die einfachste Methode ist die Verwendung einer Liste Verständnis:

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

Die Nutzung der range Funktion wird in der Regel verpönt, aber ich habe nicht ein einfacheres Verfahren noch.

gefunden
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top