python response slow when running external DLL

jfong at ms4.hinet.net jfong at ms4.hinet.net
Tue Dec 1 22:58:15 EST 2015


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



More information about the Python-list mailing list