16

結果をキューに書き込むスレッドが 1 つあります。

別のスレッド (GUI) で、次のように定期的に (IDLE イベントで) キューに結果があるかどうかを確認します。

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

これは良い方法ですか?

編集:

新しい結果を取り出さずに、待機中のスレッドが数秒間スタックすることがあるため、質問しています。

wx.WakeUpIdle「立ち往生」の問題は、推奨されているように、そのようなイベントが を呼び出すことによって実際に生成されることを確認せずに、アイドルイベントハンドラーで処理を行っていたためであることが判明しました。

4

6 に答える 6

19

利用可能なすべてのアイテムを常にキューから引き出している場合、ロック付きのリストだけでなく、キューを使用することに実際の意味はありますか? すなわち:

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

それらを個別にプルし、空のキューのブロッキング動作を利用する場合は、Queue を使用する必要がありますが、ユースケースははるかに単純に見え、上記のアプローチの方が適している可能性があります。

[Edit2] アイドルループからキューをポーリングしているという事実を見逃していました。更新から、問題は競合に関連していないことがわかります。そのため、以下のアプローチは実際には問題に関連していません. 誰かがこの便利なブロッキングバリアントを見つけた場合に備えて、私はそれを残しました:

少なくとも 1 つの結果が得られるまでブロックしたい場合は、上記のコードを変更して、プロデューサー スレッドからのシグナルによってデータが利用可能になるのを待つことができます。例えば。

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
于 2008-10-01T07:25:30.087 に答える
14

すべてのアイテムをキューから取り出す最も簡単な方法は次のとおりだと思います。

def get_all_queue_result(queue):

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

    return result_list
于 2014-09-10T14:36:49.580 に答える
9

get_nowait()リストが空の場合に呼び出しが返されないために一時停止が発生した場合、私は非常に驚かれることでしょう。

チェックの間に多数の(おそらく大きい?)アイテムを投稿している可能性があります。これは、受信スレッドに大量のデータを引き出す必要があることを意味しQueueますか?1 つのバッチで取得する数を制限してみることができます。

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

これにより、受信スレッドは一度に最大 10 個のアイテムをプルするように制限されます。

于 2008-10-01T08:45:02.640 に答える
2

キューへの書き込みが完了したら、反復ごとにキューをチェックする必要なく、qsize がそのトリックを実行するはずです。

responseList = []
for items in range(0, q.qsize()):
    responseList.append(q.get_nowait())
于 2015-02-17T21:05:44.517 に答える
1

ドキュメントによると、「アイテムがすぐに利用可能な場合はアイテムを返し、そうでない場合は空の例外を発生させる」 get_nowait() を使用しているようです

ここで、Empty 例外がスローされたときにループから抜け出します。したがって、キューにすぐに利用できる結果がない場合、関数は空の項目リストを返します。

代わりに get() メソッドを使用しない理由はありますか? 同じ瞬間にキューが put() 要求を処理しているため、get_nowait() が失敗する場合があります。

于 2008-10-01T06:12:36.267 に答える