【问题标题】:Is tkinter's `after` method thread-safe?tkinter 的 `after` 方法是线程安全的吗?
【发布时间】:2019-09-26 14:11:45
【问题描述】:

由于 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()从中依次执行任务
  • 好吧,after() 只是 tkinter 管理在特定时间后运行的事件的方式。这与直接调用函数/命令没有什么不同,只是稍后再调用。我不相信它与它正在调用的线程任务有任何交互。我不在这样的线程中使用全局命名空间,所以我不确定。我通常将任何需要更新的内容传递给线程,然后从那里进行更改。
  • 如果 "由于 tkinter 不是线程安全的!"True 那么 "是 root.after线程安全?”不能是True
  • @Mike-SMT 我不认为这是真的:“这与直接调用函数/命令没有什么不同,只是稍后再执行。” .这是一个显着的区别,因为调用 after 只是向队列中添加了一些东西,它不会触及内部的小部件对象。
  • 您阅读以下答案了吗?这可能是关于线程的最权威的答案,因为它是由 Tcl 开发人员之一编写的:stackoverflow.com/a/38767665/7432

标签: python multithreading tkinter thread-safety


【解决方案1】:

after 是线程安全的,因为它是根据 call 实现的,如果 CPython 和 Tcl 构建时使用线程支持(最常见的情况),则根据 CPython source code 通常是线程安全的。这意味着相当多的 tkinter 方法是线程安全的,但不是全部(尤其是 eval)。

如果您从其他 CPython 线程调用 after(或 call),它实际上会向主线程(使用 Tcl 解释器)发送线程安全消息,以实际与 Tcl API 交互并运行主线程中的命令。

【讨论】:

    猜你喜欢
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2013-03-31
    相关资源
    最近更新 更多