python退出mainloop_不要阻塞tkinter的mainloop
最近被GUI多線程代碼的死鎖問題搞的有點頭大,本文總結一下自己的所思所得,并不代表完全正確,因為畢竟沒有去閱讀tk的源代碼。
mainloop,故名思議,它就應該是python程序的mainThread。這個GUI的mainloop,靠事件響應驅動。比如有一個button(A),點A,就是給這個mainloop傳遞了一個事件,這個事件最后會傳遞到A綁定的commnad函數中去執行。
不要阻塞tkinter的mainloop,就是不要在事件響應的函數中阻塞住,否則GUI會卡死。常見的現象是,A綁定的函數執行需要那么一點點時間,點擊下去后,GUI就會卡住那么一點點時間。所以,大多數編程教材都建議使用多線程來規避GUI的卡死,即點擊A后啟動一個線程,A綁定的函數立即返回,釋放GUI(表示GUI有可能接收別的事件的響應了),具體工作由線程完成。
由線程來完成工作,并規避GUI的卡死,是個很好的最佳實踐,不過,我遇到的問題是,線程被GUI卡死了!
計算模型大概是這樣的:多個線程通過操作一個Text控件就是往里寫log;寫log的執行流程代碼中,有mutex,用來多線程間控制Text的狀態;GUI的事件響應中,也有mutex.acquire;只要GUI出發這個事件,整個程序就死鎖了。
為什么會這樣呢?我想來想去,覺得出問題的地方,就是線程被GUI卡死了。為什么線程會被卡死呢?因為線程在mutex.acquire中在向GUI發事件(操作Text),而此時GUI在等待mutex,于是死鎖。
GUI在一個事件沒有處理完的情況下,是無法處理別的事件的。比如我們在A的綁定函數中sleep,整個GUI上其它地方都點不了(OS會記錄這些事件,在GUI被釋放后再把這些事件灌給它)。線程中對Text的操作無法返回,很可能就是因為GUI已經被卡死了。
奇怪的是,如果A綁定代碼中也操作Text,不會卡死,而只是在GUI被釋放后,一口氣把所有的log全顯示出來,log顯示的過程只是感覺不流暢而已。區別在于mainloop中觸發事件和非mainloop中觸發(我個人的理解哈),也許存在內部事件和外部事件這樣的區別,外部事件會被阻塞,即線程操作Text的代碼被阻塞,而mainloop中操作Text的代碼,只是更新延后。
總之,在GUI中如果有mutex.acquire這樣的代碼,是非常危險的,一不留神就死鎖。不要阻塞mainloop的事件響應,用線程是OK的,用戶友好。多線程之間有mutex沒問題,只要GUI的mainloop沒有被卡死。
-- EOF --
總結
以上是生活随笔為你收集整理的python退出mainloop_不要阻塞tkinter的mainloop的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 守护进程_网络工程师之lin
- 下一篇: java 字符串转查找_Java 实例