I'm automating some windows stuff with Python, using PIL to take screenshots and such. the issue is that sometimes, deep in some function, I'll do a time.sleep(1)
and the GUI app I'm interfacing with will freeze for that second. This is weird cause doing time.sleep
in other places doesn't cause the freeze. I haven't been able to determine exactly what causes the freeze and what doesn't.. it's happened both in threads besides the main thread a开发者_如何学运维nd in the main thread.
Any ideas? I feel I just need like a "chill out" function to cause Python to stop whatever it is it's doing, let the targeted UI recover and refresh and process input, then bring it back to Python. What function would do that? (windows Sleep
function seems to act just like python's time.sleep
.)
I feel I just need like a "chill out" function to cause Python to stop whatever it is it's doing, let the targeted UI recover and refresh and process input, then bring it back to Python. What function would do that?
Calling sleep()
(any variant of it) will block execution of the thread from which you call it. This is simply the last thing you want to do if you wish to have responsive UI in that thread. Put simply, once you go to sleep, you can't do anything!
When you have non-responsive user interface, that indicates that a long-running task is executing in the thread which processes the UI, or the UI thread is blocking. So, to follow the logic through, if your 1 second sleeps (they are really dozes rather than proper sleeps!) are causing the UI to hang, they must be occurring in the same thread as the UI, or a thread which the UI is waiting.
I don't really know how you are using PIL and how you interact with the app whose image you are scraping, but it doesn't seem too likely that you are injecting into that other process. So I'd guess that process is waiting on your thread. If that is so then there is no real shortcut to solving your problem. You simply need to spend less time doing whatever it is you are doing. Calling sleep()
can only make things worse.
Calling SwitchToThread()
can't help much either. All it will do is allow another thread to run (if there's one waiting and ready to run), but you want the thread you are in to run. It won't make much difference anyway because the system will know that your thread wants to run and will schedule it again in due course.
The bottom line is that you have code running in a UI process that is blocking that process. You simply need to make it happen as quickly as possible to minimize the interference.
You probably don't want the current thread to sleep, but rather give the application a chance to process its messages.
Since it's difficult to delegate to the application's main message pump, traditionally most long-running tasks call their own temporary message pump.
def process_messages():
msg = wintypes.MSG ()
while user32.GetMessageA (byref (msg), None, 0, 0) != 0:
user32.TranslateMessage (byref (msg))
user32.DispatchMessageA (byref (msg))
The Microsoft-blessed version is here. The code will deliver events to the event loop of the application that launched your thread, and return when the event queue becomes empty.
I looked a bit in the Python and third party libraries for an implementation of the functionality, but didn't find it on such a quick search.
In short, you should do something like the above in a call to your own process_messages()
function, like it was done in Visual Basic and several other Windows-only languages, and avoid calling sleep()
.
p.s. You could tweak the message pump to pump messages only until the task you're waiting for is done.
Oh SwitchToThread
seems promising. Or in Python lingo, ctypes.windll.kernel32.SwitchToThread()
.
EDIT: Hmm doesn't seem to quite do it...
精彩评论