我正在研究一个python项目,该项目轮询COM端口上的数据并轮询用户输入。截至目前,该计划正在顺利运作,但似乎效率低下。我在一个单独的线程中运行的while循环中发生了串行端口轮询,并将数据粘贴到队列中。用户输入轮询也发生在一个while循环中,该循环在一个单独的线程中运行,该输入将输入粘贴到队列中。不幸的是,我有太多的代码和帖子,它会从问题的角度来看。
那么是否有更有效的方法来轮询串行或raw_input()而不将它们放在无限循环中并在自己的线程中运行它们?
我一直在对这个主题进行大量研究,并不断遇到“单独的线程和队列”范例。但是,当我运行这个程序时,我在四核i7上使用了近30%的CPU资源。必须有更好的方法。
我曾在C中使用过ISR,并希望有类似于我可以使用的中断。我最近的研究发现了许多带有回调的“事件”库,但我似乎无法理解它们如何适应我的情况。我正在使用Windows 7(64位)计算机进行开发,但是当我完成时将成品移动到RPi。我不是在寻找代码,我只需要指向正确的方向。感谢您提供任何信息。
答案 0 :(得分:5)
您看到CPU使用率很高,因为您的主线程正在使用非阻塞get_nowait
调用在无限循环中轮询两个不同的队列,这意味着您的循环将大部分时间不断循环。不断运行循环使用CPU周期,就像任何紧密的无限循环一样。为了避免使用大量CPU,您希望让无限循环使用阻塞I / O,以便它们等到实际要处理的数据再继续之前。这样,您就不会经常运行循环,因此使用CPU。
所以,用户输入线程:
while True:
data = raw_input() # This blocks, and won't use CPU while doing so
queue.put({'type' : 'input' : 'data' : data})
COM线程:
while True:
data = com.get_com_data() # This blocks, and won't use CPU while doing so
queue.put({'type' : 'COM' : 'data' : data})
主线程:
while True:
data = queue.get() # This call will block, and won't use CPU while doing so
# process data
阻止get
调用只会等到另一个线程中put
使用threading.Condition
对象唤醒它。这不是重复的民意调查。来自Queue.py
:
# Notify not_empty whenever an item is added to the queue; a
# thread waiting to get is notified then.
self.not_empty = _threading.Condition(self.mutex)
...
def get(self, block=True, timeout=None):
self.not_empty.acquire()
try:
if not block:
if not self._qsize():
raise Empty
elif timeout is None:
while not self._qsize():
self.not_empty.wait() # This is where the code blocks
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = _time() + timeout
while not self._qsize():
remaining = endtime - _time()
if remaining <= 0.0:
raise Empty
self.not_empty.wait(remaining)
item = self._get()
self.not_full.notify()
return item
finally:
self.not_empty.release()
def put(self, item, block=True, timeout=None):
self.not_full.acquire()
try:
if self.maxsize > 0:
if not block:
if self._qsize() == self.maxsize:
raise Full
elif timeout is None:
while self._qsize() == self.maxsize:
self.not_full.wait()
elif timeout < 0:
raise ValueError("'timeout' must be a non-negative number")
else:
endtime = _time() + timeout
while self._qsize() == self.maxsize:
remaining = endtime - _time()
if remaining <= 0.0:
raise Full
self.not_full.wait(remaining)
self._put(item)
self.unfinished_tasks += 1
self.not_empty.notify() # This is what wakes up `get`
finally:
self.not_full.release()