Ideal thread structure question (includes multi-threading)

I am writing an application that listens to sound events (using messages sent using Open Sound Control), and then pauses or resumes the program based on these events. My structure works most of the time, but always fires in the main loop, so I assume this is a thread issue. Here is a general, simplified version of what I'm talking about:

import time, threading class Loop(): aborted = False def __init__(self): message = threading.Thread(target=self.message, args=((0),)) message.start() loop = threading.Thread(target=self.loop) loop.start() def message(self,val): if val > 1: if not self.aborted: self.aborted = True # do some socket communication else: self.aborted = False # do some socket communication def loop(self): cnt = 0 while True: print cnt if self.aborted: while self.aborted: print "waiting" time.sleep(.1); cnt += 1 class FakeListener(): def __init__(self,loop): self.loop = loop listener = threading.Thread(target=self.listener) listener.start() def listener(self): while True: loop.message(2) time.sleep(1) if __name__ == '__main__': loop = Loop() #fake listener standing in for the real OSC event listener listener = FakeListener(loop) 

Of course, this simple code works fine, so it clearly does not fully illustrate my real code, but you get this idea. What is not included here is also due to the fact that pause and resume on each loop (by setting aborted = True / False) leads to some socket connection, which also includes streams.

What always happens in my code is that the main loop does not always work when it stops after an audio event. He will work for several events, but in the end he simply does not respond.

Any suggestions on how to structure such a relationship between threads?

UPDATE:

OK, I think I did it. there is a modification here that seems to work. There is a listener thread that periodically places a value in a Queue object. there is a control thread that continues to check the queue, looking for the value, and as soon as she sees that it sets the logical value to the opposite state. that a boolean controls whether the loop continues or waits for the loop.

I'm not quite sure what the q.task_done () function does here.

 import time, threading import Queue q = Queue.Queue(maxsize = 0) class Loop(): aborted = False def __init__(self): checker = threading.Thread(target=self.checker) checker.setDaemon(True) checker.start() loop = threading.Thread(target=self.loop) loop.start() def checker(self): while True: if q.get() == 2: q.task_done() if not self.aborted: self.aborted = True else: self.aborted = False def loop(self): cnt = 0 while cnt < 40: if self.aborted: while self.aborted: print "waiting" time.sleep(.1) print cnt cnt += 1 time.sleep(.1) class fakeListener(): def __init__(self): listener = threading.Thread(target=self.listener) listener.setDaemon(True) listener.start() def listener(self): while True: q.put(2) time.sleep(1) if __name__ == '__main__': #fake listener standing in for the real OSC event listener listener = fakeListener() loop = Loop() 
+2
source share
1 answer

Umm .. I do not quite understand your question, but I will do my best to explain that I think you need to fix your problems.

1) The thread of your Loop.loop function must be installed as a daemon thread so that it exits with your main thread (so you do not need to kill the python process every time you want to close your program), To do this, just put a loop. setDaemon (True) before you call the "start" function of the stream.

2) The easiest and most fault-tolerant way to communicate between threads is to queue. An element will be placed in this thread in the queue, and another thread will output the element, do something with the element, and then complete (or receive another task)

In python, Queue can be anything from the global list for python's built-in Queue object. I recommend python Queue because it is thread safe and easy to use.

+4
source

All Articles