Windows 上线程和 PyGTK 的执行顺序
我在 Windows 上遇到线程和 PyGTK 问题。 根据 PyGTK FAQ (以及我的自己的实验),从子线程可靠地更新 GUI 的唯一方法是使用 gobject.idle_add 函数。 但是,无法保证何时调用该函数。 如何保证 gobject.idle_add 后面的行在它指向的函数之后被调用?
非常简单且人为的示例:
import gtk
import gobject
from threading import Thread
class Gui(object):
def __init__(self):
self.button = gtk.Button("Click")
self.button.connect("clicked", self.onButtonClicked)
self.textEntry = gtk.Entry()
self.content = gtk.HBox()
self.content.pack_start(self.button)
self.content.pack_start(self.textEntry)
self.window = gtk.Window()
self.window.connect("destroy", self.quit)
self.window.add(self.content)
self.window.show_all()
def onButtonClicked(self, button):
Thread(target=self.startThread).start()
def startThread(self):
#I want these next 2 lines to run in order
gobject.idle_add(self.updateText)
print self.textEntry.get_text()
def updateText(self):
self.textEntry.set_text("Hello!")
def quit(self, widget):
gtk.main_quit()
gobject.threads_init()
x = 桂()
gtk.main()
I'm having issues with threads and PyGTK on Windows. According the the PyGTK FAQ (and my own experimentation), the only way to reliably update the GUI from a child thread is to use the gobject.idle_add
function. However, it can't be guaranteed when this function will be called. How can I guarantee that the line following the gobject.idle_add
gets called after the function it points to?
Very simple and contrived example:
import gtk
import gobject
from threading import Thread
class Gui(object):
def __init__(self):
self.button = gtk.Button("Click")
self.button.connect("clicked", self.onButtonClicked)
self.textEntry = gtk.Entry()
self.content = gtk.HBox()
self.content.pack_start(self.button)
self.content.pack_start(self.textEntry)
self.window = gtk.Window()
self.window.connect("destroy", self.quit)
self.window.add(self.content)
self.window.show_all()
def onButtonClicked(self, button):
Thread(target=self.startThread).start()
def startThread(self):
#I want these next 2 lines to run in order
gobject.idle_add(self.updateText)
print self.textEntry.get_text()
def updateText(self):
self.textEntry.set_text("Hello!")
def quit(self, widget):
gtk.main_quit()
gobject.threads_init()
x = Gui()
gtk.main()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要尝试从线程更新或访问 GUI。 你只是自找麻烦。 例如,“
get_text
”在线程中完全工作几乎是一个意外。 您也许可以在 GTK 中依赖它 - 尽管我什至不确定 - 但您无法在其他 GUI 工具包中这样做。如果您确实需要在线程中执行某些操作,则应该在启动线程之前从 GUI 获取所需的数据,然后使用
idle_add
,就像这样:如果你真的、绝对需要在线程中间从 GUI 读取数据(这是一个非常糟糕的主意,不要这样做 - 你可能会陷入真正令人惊讶的死锁,尤其是当程序运行时)关闭)Twisted 中有一个实用程序, blockingCallFromThread< /a>,这将为您完成艰苦的工作。 你可以这样使用它:
如果你想看看魔法是如何工作的,你可以随时 阅读源代码。
Don't try to update or access your GUI from a thread. You're just asking for trouble. For example, the fact that "
get_text
" works at all in a thread is almost an accident. You might be able to rely on it in GTK - although I'm not even sure about that - but you won't be able to do so in other GUI toolkits.If you have things that really need doing in threads, you should get the data you need from the GUI before launching the thread, and then update the GUI from the thread by using
idle_add
, like this:If you really, absolutely need to read data from the GUI in the middle of a thread (this is a really bad idea, don't do it - you can get into really surprising deadlocks, especially when the program is shutting down) there is a utility in Twisted, blockingCallFromThread, which will do the hard work for you. You can use it like this:
If you want to see how the magic works, you can always read the source.
您可以将这两个函数包装到另一个函数中,并在此函数上调用idle_add:
You could wrap the two functions into another function and call idle_add on this function: