Peter Otten at 2015/12/1 UTC+8 7:01:55PM wrote: > While the var_status.set() invoked from the second thread modifies some > internal data the main thread could kick in and modify (parts of) that same > data, thus bringing tkinter into an broken state. A simple example that > demonstrates the problem: > > import random > import threading > import time > > account = 70 > > def withdraw(delay, amount): > global account > if account >= amount: > print("withdrawing", amount) > account -= amount > else: > print("failed to withdraw", amount) > > threads = [] > for i in range(10): > t = threading.Thread( > target=withdraw, > kwargs=dict(delay=.1, > amount=random.randrange(1, 20))) > threads.append(t) > t.start() > > for t in threads: > t.join()
It's a simple and vivid example. You must be in the banking business:-) In this exercise, I can just use update_idletasks() method to solve the deferred display problem of tkinter, and forget all about thread. But what if I really want to use thread for the long-running DLL function in the download hander? I didn't figure out a correct way of doing it at this moment. Maybe queue is the answer but I am not familiar with it yet. def download(): var_status.set(...) #showing a start-up message result = SayHello() #this is a long-running function if result.... #according to the result, display more messages .... > > Before every withdrawal there seems to be a check that ensures that there is > enough money left, but when you run the script a few times you will still > sometimes end with a negative balance. That happens when thread A finds > enough money, then execution switches to thread B which also finds enough > money, then both threads perform a withdrawal -- oops there wasn't enough > money for both. > > >> Another complication that inevitably comes with concurrency: what if the > >> user triggers another download while one download is already running? If > >> you don't keep track of all downloads the message will already switch to > >> "Download OK" while one download is still running. > > > > Hummm...this thought never comes to my mind. After take a quick test I > > found, you are right, a second "download" was triggered immediately. > > That's a shock to me. I suppose the same event shouldn't be triggered > > again, or at least not triggered immediately, before its previous handler > > was completed. ...I will take a check later on Borland C++ builder to see > > how it reacts! > > > > Anyway to prevent this happens? if Python didn't take care it for us. > > A simple measure would be to disable the button until the download has > ended. Good! simple and work. I shouldn't say "Python should take care of it", but "tk" should do. It's annoying the widget's command was re-triggered before it was finished. (my personal opinion:-) -- https://mail.python.org/mailman/listinfo/python-list