0

I'm trying a GUI application in which I am using threading to create concurrently executed tasks. Here is the code:

from tkinter import *
from threading import *
import time
kill = False

def mainer():
    global kill
    while not kill:
        maintext.set(value='bbb')


def quitfunc():
    global kill
    kill = True
    time.sleep(2)
    root.destroy()



root=Tk()
maintext=StringVar(value='aaa')
Thread(target=mainer).start()
root.protocol("WM_DELETE_WINDOW", quitfunc)
root.mainloop()

ISSUES:

  1. As it currently stands, on closing the root window, the process doesn't stop. It keeps running. Even if I add an infinite loop to print isalive() for the mainer thread, it keeps saying True. Why does it not quit?
  2. In case I add a print(kill) statement in the mainer function, I get one of the two outcomes:
    1. If written above the maintext.set() statement, on quitting the window, the print stops getting executed but the thread still does not quit. Very very rarely, it does, which I am assuming must depend on which line the function was on when the quit function was executed.
    2. If written below that statement, on quitting, the thread almost inevitably quits.

I have no clue what is happening here. Any help is appreciated.

stochastic13
  • 423
  • 2
  • 15
  • have you tried adding a `time.sleep()` in your loop? maybe, just maybe, the thread is too busy sending commands to tkinter. – Jean-François Fabre May 04 '17 at 14:40
  • 1
    @Jean-FrançoisFabre I want to understand the logic behind the behaviour. Why should that be necessary? And the actual project requires reading from the USB serial, wouldn't `time.sleep()` cause delays? – stochastic13 May 04 '17 at 14:42
  • 1
    @Jean-FrançoisFabre In that case, irrespective of where I put the `print(kill` statement, I should have the same result? – stochastic13 May 04 '17 at 14:46
  • 2
    that reminds me of something: I think it's not safe to perform GUI operations from threads. I don't know tkinter, but `wxWidgets` has a `callAfter` method that asks the main thread to perform the action. Performing the action in a subthread leads to undefined behaviour – Jean-François Fabre May 04 '17 at 15:09
  • 1
    bingo: http://stackoverflow.com/questions/14168346/python-tkinter-with-threading-causing-crash – Jean-François Fabre May 04 '17 at 15:10
  • @Jean-FrançoisFabre But it seems that parallel processing is seemingly indispensable to what I want to build. I need 2 background threads, one reading the USB serial and updating several global variables real time. And the other, updating the GUI. – stochastic13 May 04 '17 at 15:11
  • @Jean-FrançoisFabre And what exactly is the reason why the threads behave differently with a different arrangement of the statements. Academic curiosity! – stochastic13 May 04 '17 at 15:18
  • Possible duplicate of [python tkinter with threading causing crash](https://stackoverflow.com/questions/14168346/python-tkinter-with-threading-causing-crash) – ivan_pozdeev Apr 18 '18 at 12:40

1 Answers1

2

If you make the thread a daemon it will die when the main thread dies, so you don't need any of the quit logic at all:

from tkinter import *
from threading import *
import time

def mainer():
    while True:
        maintext.set(value='bbb')
    time.sleep(.1) # just so my CPU does not rail

root=Tk()
maintext=StringVar(value='aaa')
t = Thread(target=mainer)
t.daemon = True
t.start()
root.mainloop()
Novel
  • 13,406
  • 2
  • 25
  • 41