Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all items from thread Queue

I have one thread that writes results into a Queue.

In another thread (GUI), I periodically (in the IDLE event) check if there are results in the queue, like this:

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

Is this a good way to do it ?

Edit:

I'm asking because sometimes the waiting thread gets stuck for a few seconds without taking out new results.

The "stuck" problem turned out to be because I was doing the processing in the idle event handler, without making sure that such events are actually generated by calling wx.WakeUpIdle, as is recommended.

like image 634
Eli Bendersky Avatar asked Oct 01 '08 05:10

Eli Bendersky


People also ask

How to share a queue among three threads in Java?

Share a queue among three threads A, B, C as per given norms : Thread A generates random integers and pushes them into a shared queue. Threads B and C compete with each other to grab an integer from the queue. The threads B and C compute the sum of integers that they have grabbed from the queue.

What is the difference between get() and task_done() in threading?

When a thread calls the get () method to get the item from the queue, it may need to process it before the task is considered completed. Once completed, the thread may call the task_done () method of the queue to indicate that it has processed the task completely:

How many threads does a processqueue start out with?

By default, the ProcessQueue starts out with one worker thread. This is suitable for asynchronous processing of the items in the ProcessQueue when the time to complete is not as important as conserving resources, or when it’s essential that items in the ProcessQueue be processed in the same order as they were entered.

Should I use queue or pull from a specific queue?

If you're also pulling them individually, and making use of the blocking behaviour for empty queues, then you should use Queue, but your use case looks much simpler, and might be better served by the above approach.


1 Answers

If you're always pulling all available items off the queue, is there any real point in using a queue, rather than just a list with a lock? ie:

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

If you're also pulling them individually, and making use of the blocking behaviour for empty queues, then you should use Queue, but your use case looks much simpler, and might be better served by the above approach.

[Edit2] I'd missed the fact that you're polling the queue from an idle loop, and from your update, I see that the problem isn't related to contention, so the below approach isn't really relevant to your problem. I've left it in in case anyone finds a blocking variant of this useful:

For cases where you do want to block until you get at least one result, you can modify the above code to wait for data to become available through being signalled by the producer thread. Eg.

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
like image 146
Brian Avatar answered Sep 23 '22 11:09

Brian