tkinter的`after`方法是否线程安全?

5

由于 tkinter 不是线程安全的,我经常看到人们使用 after 方法将一些代码排队在主线程中执行。以下是一个示例:

import tkinter as tk
from threading import Thread

def change_title():
    root.after(0, root.title, 'foo')

root = tk.Tk()
Thread(name='worker', target=change_title).start()
root.mainloop()

所以,我们不直接在worker线程中执行root.title('foo'),而是使用root.after将其加入队列,让主线程来执行它。但是,调用root.after和调用root.title一样糟糕吗?root.after是线程安全的吗?


我猜root.after会在队列中添加一个任务,这些任务将按顺序由root.mainloop()逐个执行。 - Lev Leontev
well after() 就是 tkinter 执行特定时间后管理事件的方法。这与直接调用函数/命令没有任何区别,只是稍后执行而已。我不认为它会与调用的线程任务有任何交互。我不会在线程内这样使用全局命名空间,所以我不确定。通常我会将需要更新的任何内容传递给线程,然后从那里进行更改。 - Mike - SMT
1
如果“因为tkinter不是线程安全的!”为真,则“root.after是否线程安全?”不能为真吗? - stovfl
@Mike-SMT 我不认为这是正确的:_"它与直接调用函数/命令没有任何区别,只是稍后执行而已。"_ 这是一个显著的区别,因为调用 after 只是将某些内容添加到队列中,而不会触及内部小部件对象。 - Bryan Oakley
@BryanOakley 哦,好的,了解了。如果你从另一个线程运行 update(),听起来可能会引起一些问题。 - Mike - SMT
显示剩余4条评论
1个回答

2
after是线程安全的,因为它是基于call实现的,而根据CPython 源代码,如果CPython和Tcl构建了线程支持(最常见的情况),则call通常是线程安全的。这意味着相当大一部分tkinter方法是线程安全的,但并非全部(特别是eval)。
如果您从其他CPython线程调用after(或call),它实际上会向主线程(带有Tcl解释器)发送线程安全消息,以实际与Tcl API交互并在主线程中运行命令。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接