Search code examples
pythonpython-3.xtkinterpython-multithreading

Call a function in main thread once threaded function is completed


I am building a Tkinter GUI and I have a process that takes a while to complete, so I threaded it to prevent the GUI from hanging. Lets call the threaded function foo. Once foo is completed, I need to call another function, bar. bar needs to be called from the main thread (it uses a matplotlib method that does not work inside of a thread).

I can't seem to wrap my head around how I might do this. I thought about joining the thread, but that just causes the GUI to hang. I also thought about using a signal variable that I would change in the last line of foo to tell the rest of my program that it is done and its time to execute bar, but then I couldn't figure out how I could continuously check that variable in the main thread without hanging the GUI. Any ideas?

Using Python 3.7


Solution

  • You can use threading.Event() object to notify the main thread and use after() to call a function periodically to check the Event() object to determine when to call bar().

    Below is a simple example:

    import tkinter as tk
    import threading
    import time
    
    def foo(event):
        print('foo started')
        time.sleep(5)
        print('foo done')
        # notify main thread
        event.set()
    
    def bar():
        print('hello')
    
    def check_event(event, callback):
        print('.', end='')
        if event.is_set():
            # thread task is completed
            callback()
        else:
            # check again 100 ms (adjust this to suit your case) later
            root.after(100, check_event, event, callback)
    
    root = tk.Tk()
    
    # create the `Event()` object
    event = threading.Event()
    # start the checking
    check_event(event, bar)
    # start the thread task
    threading.Thread(target=foo, args=(event,)).start()
    
    root.mainloop()