Is tkinter's `after` method thread-safe?
Asked Answered
G

1

6

Since tkinter isn't thread-safe, I often see people use the after method to queue some code for execution in the main thread. Here's an example:

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()

So instead of executing root.title('foo') directly in the worker thread, we queue it with root.after and let the main thread execute it. But isn't calling root.after just as bad as calling root.title? Is root.after thread-safe?

Gaussmeter answered 26/9, 2019 at 14:11 Comment(9)
I guess root.after adds a task in a queue, from which the tasks are executed sequentially by root.mainloop()Outside
Well after() is simply tkinter's way of managing events to be run after a specific time. It is no different than just calling the function/command directly but simply done at a later time. I do not believe it has any interaction with the threaded task it is calling. I don't work with the global namespace from within a thread like this though so I am not sure. I typically pass anything that needs to be updated to the thread and then make changes from there.Caparison
If "Since tkinter isn't thread-safe!" is True then "Is root.after thread-safe?" can't be True?Burhans
@Mike-SMT I don't think this is true: "It is no different than just calling the function/command directly but simply done at a later time. ". It's a significant difference, in that calling after simply adds something to a queue, it doesn't touch the internal widget objects.Opportuna
Have you read the following answer? It is probably the most authoritative answer on threading, given that it was written by one of the Tcl developers: https://mcmap.net/q/1914945/-callback-to-python-function-from-tkinter-tcl-crashes-in-windowsOpportuna
@BryanOakley I hadn't seen that, thanks. Sounds like a "no" to me.Gaussmeter
@BryanOakley That makes sense. So by assigning an event to occur say to root then does that mean the event is actually occurring in the main thread and has no issues from being assigned during a threaded function?Caparison
@Mike-SMT: Assuming that mainloop pulls the item off of the queue, it will be run in whatever thread mainloop is running in -- which is presumably the main thread. However, if you call update from some other thread, it will probably be run in that thread.Opportuna
@BryanOakley oh ok good to know. If you run update() from another thread that sounds like it could cause some issues.Caparison
A
3

after is thread-safe because it is implemented in terms of call which is generally thread-safe according to the CPython source code if CPython and Tcl were built with thread support (the most common case). This means quite a large footprint of tkinter methods are thread-safe, but not all (particularly eval).

If you call after (or call) from some other CPython thread, it will actually send a thread-safe message to the main thread (with the Tcl interpreter) to actually interact with the Tcl API and run the command in the main thread.

Allerie answered 7/6, 2020 at 19:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.