[Tutor] Changing instance attributes in different threads

Michael Lange klappnase at freenet.de
Wed Feb 8 22:33:55 CET 2006


On Wed, 08 Feb 2006 13:47:39 -0500
Kent Johnson <kent37 at tds.net> wrote:

> >     while self.recording:
> >         data = []
> >         while not self.rec_queue.empty():
> >             try:
> >                data.append(self.rec_queue.get(block=0))
> >             except Queue.Empty:
> >                break
> >         for d in data:
> >             self._waveobj.writeframesraw(d)

> I don't understand why this is better than my code. It's a little 
> different - you get all the data, then write all the data; I get a 
> little, write a little - but since you are writing one datum at a time 
> in both cases, I don't know why it would make much difference.
> 

Sorry, I missed to insert the time.sleep(0.1) I used in my original while loop into the example above.
The reason for using time.sleep() is that I need to avoid lots of loops over an empty buffer.
The amount of time until the producer thread reads a new data fragment into the buffer may
be significant, depending on the fragment size requested by the driver (e.g my fm801 card
wants fragments of 16384 bytes which is about 0.09 audio seconds). On the other hand the
buffer may contain hundreds of kB of data if other processes cause a lot of disk I/O.

> You should be able to take the try/except out of your version, since 
> this code is the only consumer from the Queue, if queue.empty() is 
> false, queue.get() should succeed.
> 

Not if I call it with block=0; if I understand the docs correctly the queue will raise a Queue.Empty exception
if the queue is currently locked by another thread. 

> In the vu meter thread I can see you might want to consume a minimum 
> length of data but again that doesn't seem so hard.
> 
> OTOH your latest code looks OK too, this was just a suggestion.
> 

It was a good suggestion, I never looked at the Queue class before, and it's definitely good to know about it.
In my special case here, your other suggestion of using Condition() seems to allow me easier handling of
my buffers, though. Another part of my code I did not post here that is executed when the recording
is stopped (i.e. self.recording is set to 0) also seems to be easier to implement with the Condition technique.

> > All Tkinter access must be from the main thread (or, more precisely,
> the thread that called mainloop).
> 
> OK, yes. What this means is that any code that changes the state of the 
> GUI should be called from the main thread. In your case, that means that 
> the thread that updates the vu meter must be the main thread. If you are 
> calling get_peaks() from a scheduled Tkinter task (scheduled with 
> after() or after_idle()) you will be fine.
> 
Yes, that's what I am doing. I think I just was confused because I did not understand what the Condition class does.
Now I think I see clearer, thanks for all your help.

Michael





More information about the Tutor mailing list