我有一个程序,通过Jack连接记录来自火线设备(FA-66)的音频。接口是使用pygtk创建的,并使用py-jack(http://sourceforge.net/projects/py-jack/)进行录制。录制在不同的线程中完成,因为必须同时使用GUI才能查看音频结果。
问题在于,当我启动录制线程时,GUI的响应变得非常慢。我在主线程的开头有gtk.gdk函数start_threads()。如果我做对了,我不需要threads_enter()和threads_leave(),因为录制不会影响GUI。如果我错了,请纠正。
函数jack.process()记录来自三个麦克风的音频。如果我用time.sleep(2)替换它,一切正常。
在这种情况下创建线程的最佳方法是什么?为什么jack.process会冻结GUI?是否需要所有cpu时间或其他东西? 我的代码示例如下:
soundrecorder.py:
...
def start(self):
Thread(target=self._start).start()
def _start(self):
while self.eventhandler.record.isSet():
data = self._jackRecord(self.sample_length)
self.datahandler.queue.put(data)
def _jackRecord(self, length):
capture = Numeric.zeros((self.inputs, int(self.sample_rate * length)), 'f')
output = Numeric.zeros((self.inputs, self.buffer_size), 'f')
i = 0
while i < capture.shape[1] - self.buffer_size:
try:
jack.process(output, capture[:,i:i+self.buffer_size])
i += self.buffer_size
except:
pass
return capture
eventhandler.py: recordStart()和recordStop()只是在按下开始和停止按钮时调用的回调函数。
...
def recordStart(self, widget, data=None):
if not self.record.isSet():
self.record.set()
self.soundrecorder = SoundRecorder(self, self.datahandler)
self.soundrecorder.connect()
self.soundrecorder.start()
def recordStop(self, widget, data=None):
if self.record.isSet():
self.record.clear()
del(self.soundrecorder)
答案 0 :(得分:2)
你误解了线程是如何工作的。
在这种情况下,线程无法帮助您。
“然后,当记录一个样本时,将对其进行分析并得到结果 在GUI中显示。与此同时 下一个样本已经存在 录“。
<强> WRONG 即可。线程不会同时做两件事。在python中有一个全局锁,它阻止两个线程同时运行python代码或触摸python对象。除此之外,如果您没有两个CPU或核心,则有两件事情不会同时发生。线程机制只是在它们之间切换,每次执行固定数量的指令。
线程还为无益添加处理,内存和代码复杂性开销。与使用单线程相比,使用线程的Python代码运行更慢并具有更低的性能。此规则只有少数例外,您的案例不是其中之一。
您可能希望将录制循环重写为回调并将其与GTK循环集成(您将获得比使用线程更好的性能)。
为此,请使用具有高优先级的gobject.idle_add
。
如果你想“同时”运行两件事,使用两个处理器/核心,你想要启动另一个进程。启动一个收集数据的过程,并通过一些进程间通信机制将其传输到正在分析和绘制数据的其他过程。 multiprocessing模块可以帮助您。