我有一个pygtk应用程序,只要我的python脚本打开就会运行。与gtk.main()一起,我有一个在脚本开头启动的线程,它刷新了一个gtk.TextView()实例:
def listen(self):
while True:
print "refreshing"
data = self.socket.recv(buffer_size)
if data:
self.txtBuffer.insert(self.txtBuffer.get_end_iter(), data + "\n")
print data
thread.start_new_thread(self.listen, ())
self.set_up_gui() # gtk.main()
但是,当我运行程序时,gui会打开,但不会打印“刷新”文本,也不会在发送到套接字时打印任何数据。我试图使用glib.add_idle()来为这个程序进行线程化,但是当gui空闲时(这种情况不常见),它只会运行单独的线程。谢谢!
答案 0 :(得分:2)
您正在从不同的线程访问文本缓冲区而没有任何同步,这是不受支持的。要解决此问题,请将self.txtBuffer.insert(...)
替换为gobject.idle_add(lambda: self.txtBuffer.insert(...))
。这告诉GUI线程在下一次主循环迭代时更新文本缓冲区,保证在没有显式同步的情况下工作。
您应该确保GUI线程没有被阻止,即它正在运行gtk.main()
,并且只处理GUI更新,例如上面的textBuffer.insert
。应该将长时间运行/阻塞任务委托给其他线程或进程,因为您的代码已经尝试过。实施此操作后,GUI更新将立即发生。
有关PyGTK和线程的更多详细信息,请参阅this answer。