X-Received: by 10.107.135.21 with SMTP id j21mr1624002iod.2.1449028696030; Tue, 01 Dec 2015 19:58:16 -0800 (PST) X-Received: by 10.50.128.161 with SMTP id np1mr40249igb.4.1449028696013; Tue, 01 Dec 2015 19:58:16 -0800 (PST) Path: csiph.com!optima2.xanadu-bbs.net!xanadu-bbs.net!news.glorb.com!mv3no9617115igc.0!news-out.google.com!f6ni15765igq.0!nntp.google.com!mv3no7642911igc.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.python Date: Tue, 1 Dec 2015 19:58:15 -0800 (PST) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=1.172.225.160; posting-account=G2sM6AoAAADOlDdo9rWD6sFkj3T5ULsz NNTP-Posting-Host: 1.172.225.160 References: <3ec6a016-dae5-4986-b035-c1a8cd4dc3e7@googlegroups.com> User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <78fd0a4e-50d0-49fd-8a36-94e376e45fc9@googlegroups.com> Subject: Re: python response slow when running external DLL From: jfong@ms4.hinet.net Injection-Date: Wed, 02 Dec 2015 03:58:16 +0000 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Xref: csiph.com comp.lang.python:99844 Peter Otten at 2015/12/1 UTC+8 7:01:55PM wrote=EF=BC=9A > While the var_status.set() invoked from the second thread modifies some= =20 > internal data the main thread could kick in and modify (parts of) that sa= me=20 > data, thus bringing tkinter into an broken state. A simple example that= =20 > demonstrates the problem: >=20 > import random > import threading > import time >=20 > account =3D 70 >=20 > def withdraw(delay, amount): > global account > if account >=3D amount: > print("withdrawing", amount) > account -=3D amount > else: > print("failed to withdraw", amount) >=20 > threads =3D [] > for i in range(10): > t =3D threading.Thread( > target=3Dwithdraw, > kwargs=3Ddict(delay=3D.1, > amount=3Drandom.randrange(1, 20))) > threads.append(t) > t.start() >=20 > 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 def= erred 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 downlo= ad hander? I didn't figure out a correct way of doing it at this moment. Ma= ybe queue is the answer but I am not familiar with it yet. def download(): var_status.set(...) #showing a start-up message result =3D SayHello() #this is a long-running function if result.... #according to the result, display more messages .... >=20 > Before every withdrawal there seems to be a check that ensures that there= is=20 > enough money left, but when you run the script a few times you will still= =20 > sometimes end with a negative balance. That happens when thread A finds= =20 > enough money, then execution switches to thread B which also finds enough= =20 > money, then both threads perform a withdrawal -- oops there wasn't enough= =20 > money for both. > =20 > >> Another complication that inevitably comes with concurrency: what if t= he > >> 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. > >=20 > > 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 handl= er > > was completed. ...I will take a check later on Borland C++ builder to s= ee > > how it reacts! > >=20 > > Anyway to prevent this happens? if Python didn't take care it for us. >=20 > A simple measure would be to disable the button until the download has=20 > ended. Good! simple and work. I shouldn't say "Python should take care of it", but "tk" should do. It's a= nnoying the widget's command was re-triggered before it was finished. (my p= ersonal opinion:-)