2011-03-17 36 views
2

我用Python自動化一些Windows的東西,使用PIL截屏等。問題在於,有時候,在某些功能上,我會做一個time.sleep(1),而我與之交互的GUI應用程序將在那一秒凍結。這是奇怪的原因在其他地方做time.sleep不會導致凍結。我一直無法確定究竟是什麼原因導致了凍結,什麼不是。它在除了主線程和主線程之外的線程中都發生了。python + windows自動化 - 有時窗口故障

任何想法?我覺得我只是需要像「放鬆」功能一樣,讓Python停止它正在做的任何事情,讓目標用戶界面恢復並刷新和處理輸入,然後將其帶回Python。什麼功能可以做到這一點? (窗口Sleep功能似乎就像蟒蛇的time.sleep一樣。)

+0

可能是CPythons蹩腳的線程弄亂了事情。 – schlenk 2011-03-17 23:02:55

+1

@schlenk如果是這樣,那麼CPython的蹩腳的線程如果能夠混淆不同進程的執行,就必須有很大的伸手可及。 – 2011-03-18 00:20:08

+0

請參閱http://msdn.microsoft.com/en-us/library/ms687032(v=vs.85).aspx中的備註部分如果他與Windows交互,則可能會有一個問題,因爲time.sleep()實現使用WaitForSingleObject()而不是Ex版本。 – schlenk 2011-03-18 18:42:36

回答

0

SwitchToThread看起來很有希望。或者用Python的語言,ctypes.windll.kernel32.SwitchToThread()

編輯:嗯似乎並不十分做...

+0

它不會,它所要做的就是讓另一個線程現在運行,如果有一個等待,但可能沒有,所以最有可能回到你身邊! – 2011-03-17 23:09:34

1

我覺得我只是需要像「冷靜下來」 功能造成的Python停止 不管它是它在做什麼,讓 針對性的UI恢復和刷新和 處理輸入,然後將它帶回 Python。什麼功能可以做到這一點?

調用sleep()(它的任何變體)將阻止執行您調用它的線程。如果您希望在該線程中具有響應式UI,這只是您想要做的最後一件事。簡而言之,一旦你去睡覺,你什麼都做不了!

如果您的用戶界面無響應,則表示長時間運行的任務正在處理UI的線程中執行,或者UI線程處於阻塞狀態。因此,要遵循邏輯,如果你的1秒鐘睡眠(它們真的是打盹而不是正常的睡眠!)會導致UI掛起,它們必須與UI發生在同一線程中,或者UI是等候。

我真的不知道您是如何使用PIL以及如何與應用程序的圖片進行交互,但是您注入其他進程似乎不太可能。所以我想這個過程正在等待你的線程。如果是這樣,那麼解決您的問題就沒有真正的捷徑。你只需要花更少的時間去做任何你正在做的事情。調用sleep()只會讓事情變得更糟。

調用SwitchToThread()也無濟於事。它所要做的就是允許另一個線程運行(如果有一個線程正在等待並準備運行),但您希望運行的線程運行。它不會有太大的區別,因爲系統會知道你的線程想要運行並且會在適當的時候再次安排它。

底線是,您的代碼正在阻止該進程的UI進程中運行。你只需要儘可能快地發生,以儘量減少干擾。

+0

嗯我的代碼如何最終在另一個線程中意外運行? (我不想故意這樣做)..什麼是常用方法? – Claudiu 2011-03-17 23:25:47

+0

注射並不少見。事實上,其他應用程序更可能只是在等待您的應用程序。 – 2011-03-17 23:30:29

+0

另類我可以使用「運行在另一個線程中的功能的其餘部分」的方法..聽起來真的很難看,但 – Claudiu 2011-03-17 23:30:30

1

您可能不希望當前線程進入睡眠狀態,而是讓應用程序有機會處理其消息。

由於很難將其委託給應用程序的主消息泵,傳統上最長時間運行的任務調用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)) 

微軟的祝福版本是here。該代碼將事件傳遞到啓動線程的應用程序的事件循環,並在事件隊列變空時返回。

我在Python和第三方庫中查找了一些功能的實現,但沒有在如此快速的搜索中找到它。

簡而言之,您應該在調用自己的process_messages()函數時執行上述操作,就像在Visual Basic和其他幾種僅限Windows的語言中完成的操作一樣,並且避免調用sleep()

p.s.您可以調整消息泵以僅在您等待的任務完成之前抽取消息。