Page 1 of 1

Running two functions simultaneously via Threading

Posted: Mon Feb 06, 2017 4:17 am
by register25
Hi all. I am working on a project to playback and record audio at the same time via Python. To run these two functions simultaneously, I used the Threading function. My code are as seen below:

Code: Select all

import threading
import time

def play1():
    while time.time() < start_time:
        pass
    threading.Thread(target=playAudio).start() 
def play2():
    while time.time() < start_time:
        pass
    threading.Thread(target=recordAudio).start() 


if __name__ == "__main__":
    start_time=time.time()+1

    threading.Thread(target=play1).start()
    threading.Thread(target=play2).start()
However, when I ran the code I was met with the error as below:
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/pi/0206.py", line 69, in recordAudio
data = stream.read(CHUNK)
File "build/bdist.linux-armv7l/egg/pyaudio.py", line 608, in read
return pa.read_stream(self._stream, num_frames, exception_on_overflow)
IOError: [Errno -9981] Input overflowed

KeyboardInterrupt


Can anyone kindly advise me on how to proceed from here? Thanks in advance.

Re: Running two functions simultaneously via Threading

Posted: Mon Feb 06, 2017 7:51 am
by bensimmo
Does each part work without threading?

Have you programmed for python2 or python3. I see it's using python2.

Re: Running two functions simultaneously via Threading

Posted: Mon Feb 06, 2017 2:59 pm
by register25
bensimmo wrote:Does each part work without threading?

Have you programmed for python2 or python3. I see it's using python2.
Each part does work when run separately. I am programming it for python2, does it not work on python2?

Re: Running two functions simultaneously via Threading

Posted: Mon Feb 06, 2017 8:52 pm
by bensimmo
I don't know. I only use Python3 myself.

But are you (it looks like to me) creating a thread within a thread ? (I'm not sure exactly how this works, just thinking aloud incase it jogs an idea)
e.d. creating a thread of play1, and the doing whatever pass is till it's the start time and then creating a thread of the playAudio ?

If you launch just the recordAudio directly in it's own thread (ignoring all the start times and playAudio) does it work ?


As a side, maybe some of the bits I've never looked at before (conditions, semaphores, locks, timers) could be used to start them at the same time ?
https://docs.python.org/2/library/threading.html

Re: Running two functions simultaneously via Threading

Posted: Wed May 15, 2019 10:18 am
by jomyver

Re: Running two functions simultaneously via Threading

Posted: Wed May 15, 2019 6:33 pm
by hippy
The threading shown looks fine to me. An odd way to go about it but I don't think it's a threading issue per se.

But it could be an issue of the playAudio thread starting before recordAudio, or having not started before recordAudio has filled its buffer.

Without any clue as to what the playAudio and recordAudio threads do, it's hard to say.

Re: Running two functions simultaneously via Threading

Posted: Wed May 15, 2019 6:38 pm
by Andyroo
My guess is the data has not been fully written out and the 'play' routine deletes the file...

You may also get a clash between the two time calls without adding a short delay (even 0.1 of a second would help.

I would use a queue to communicate between the two threads:

Thread 1 records audio and closes file 1
Thread 2 waits for entry on queue
Thread 1 pops 'play file 1' on the queue
Thread 2 reads file to play from queue and plays that
Thread 1 starts records file 2

etc
etc

Re: Running two functions simultaneously via Threading

Posted: Wed May 15, 2019 7:12 pm
by pootle
Python will not execute 2 threads at exactly the same time - so if you use code like

Code: Select all

while time.time() < start_time:
        pass
that thread will completely lock out all other threads. (search Python Global Interpreter Lock if you want to know more)

If the code in you playaudio / recordaudio functions are similar, then it is likely 1 will hog the machine and the other will be left in limbo.

If the code does any i/o or calls the right sort of library than there can be parallel execution.

The fact you got a buffer overflow in the record function suggests that the recorder wasn't keeping up with the incoming data.

Re: Running two functions simultaneously via Threading

Posted: Thu May 16, 2019 5:36 pm
by hippy
pootle wrote:
Wed May 15, 2019 7:12 pm
Python will not execute 2 threads at exactly the same time - so ... that thread will completely lock out all other threads.
This seems to work just fine running both threads under Windows and on a Pi -

Code: Select all

import threading
import time

def One():
  while True:
    pass

def Two():
  print "2"

threading.Thread(target=One).start()
time.sleep(5)
threading.Thread(target=Two).start()

Re: Running two functions simultaneously via Threading

Posted: Thu May 16, 2019 6:15 pm
by Andyroo
Interesting - I had assumed the pass did not do anything at all and was compiled out based on this.

Obviously the GAL is happy to switch threads as needed in this case.

If you increase the delay before starting the second thread, do you see the CPU ramp up and get the same result (no Pi handy)?

Re: Running two functions simultaneously via Threading

Posted: Fri May 17, 2019 8:49 am
by bensimmo
My rudimentary understanding,..
Isn't that because the GIL is release after some very short time, hence why for I/O it's fine, because there is a long delay in getting information back. It's just synchronization that isn't good.
You could use other Pythons where the GIL is not used (?) Try multiprocessing (but that more 'cores' than synchronization?)
This is all just throwing threads out incase one works.