tkinter 的“after”方法是线程安全的吗?

Ara*_*Fey 6 python multithreading tkinter thread-safety

由于 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()
Run Code Online (Sandbox Code Playgroud)

因此,我们不是root.title('foo')直接在worker线程中执行,而是将其排队root.after并让主线程执行它。但打电话不就root.after和打电话一样糟糕吗root.titleroot.after线程安全吗?

小智 3

after是线程安全的,因为如果 CPython 和 Tcl 是使用线程支持构建的(最常见的情况),那么call根据 CPython源代码,它是按照通常线程安全的方式实现的。这意味着相当大的占用空间的tkinter方法是线程安全的,但不是全部(特别是eval)。

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