我遇到的问题类似于这篇文章中的问题
C, junk appearing on screen using curses
但是,我正在使用python。我写了一个包装器Screen类,它以更方便的方式包装了curses模块。我喜欢这样的
def getKeyCode(self):
with self._curses_lock:
self._curses_screen.nodelay(False)
c = self._curses_screen.getch()
if c == 27:
with self._curses_lock:
self._curses_screen.nodelay(True)
next_c = self._curses_screen.getch()
with self._curses_lock:
self._curses_screen.nodelay(False)
return c
以及归结为此
的写作 with self._curses_lock:
self._curses_screen.addstr(y, x, out_string, attr)
getKeyCode由一个单独的python线程调用,该线程在getch中大部分时间都在等待,当按下一个键时,它会被添加到一个Queue中。在另一个(主)线程上,我有一个事件循环,它从队列中获取事件,执行重新绘制并刷新屏幕。
我知道ncurses持有共享状态,我添加了一堆threading.Locks以防止竞争条件,但如果我按住箭头键,偶尔我会得到垃圾。 我猜这是因为getch在ncurses中被释放,而另一个线程正在进行重新绘制。这弄乱了重画的状态,给出了奇怪的结果。我显然不能让我的getKeyCode线程持有锁,因为这意味着在getch返回之前根本不会重新绘制,也不想让getch非阻塞,因为我会1)没有真正解决问题, 2)有一个不断运行的线程,可以将CPU使用率提高到100%。我该如何解决这个问题?
答案 0 :(得分:1)
我解决了这个问题。我用
设置getch非阻塞self._curses_screen.nodelay(True)
然后我不是在curses中等待,而是在stdin上选择。当select返回时,一些东西可用,我可以锁定并获得对ncurses后端的独占访问,保证我将立即返回可用的内容并释放锁。
def getKeyCode(self):
select.select([sys.stdin], [], [])
with self._curses_lock:
c = self._curses_screen.getch()
if c == 27:
next_c = self._curses_screen.getch()
return c