Control.Invoke()
調用PostMessage()
然後等待,直到UI線程處理完消息。那麼爲什麼它不調用SendMessage()
(默認情況下會一直等到UI線程處理完消息)。爲什麼Control.Invoke()調用PostMessage()而不是SendMessage()?
4
A
回答
4
Control.Invoke()是危險方法,許多.NET程序員已經死鎖了它的程序。應該非常強烈地避免因此。簡單的日常操作就像關閉窗戶一樣危險。你會希望等到工作線程不能再調用,因爲當線程繼續運行但UI已經消失時沒有什麼好的事情發生。所以你用AutoResetEvent指示線程並等待它完成。
當線程在錯誤的時間調用Invoke()時,這樣的等待很可能導致程序死鎖。線程無法完成,因爲它停留在Invoke()調用中,UI線程無法爲其服務,因爲它處於等待狀態。一個「致命的擁抱」,兩個線程都不能取得進展,你的程序會掛起。很難調試,因爲它不可預測,並且不會經常發生,只有在線程完全同時調用Invoke時纔會出錯。
打破死鎖需要知道Invoke()調用正在進行,因此可以取消。當你使用SendMessage()時是不可知的。它阻塞的鎖隱藏在操作系統中。我最近發佈了an answer關於SendMessage的問題,您在那裏閱讀的所有內容也適用於此處。
因此,微軟並沒有這樣實施,他們使用PostMessage。他們在調用隊列中添加一個條目,調用PostMessage來喚醒UI線程,以便查看該隊列。特定於通過BeginInvoke調用,它們阻塞隊列條目中的ManualResetEvent,當UI線程完成對委託目標的調用時發出信號。
現在他們可以做一些事情來避免死鎖,當一個窗口關閉時,它會通過調用隊列來查看並取消任何具有該窗口作爲調用目標的東西。或換句話說,當您使用SendMessage並導致死鎖時,隱藏的鎖現在變得可見並且可以釋放以打破死鎖。
相關問題
- 1. SendMessage vs PostMessage + WaitForSingleObject
- 2. 我不明白如何使用SendMessage或PostMessage調用
- 3. 爲什麼,而不是使用回調
- 4. 爲什麼不調用UIPinchGestureRecognizer,而scrollViewDidEndZooming是?
- 5. 爲什麼需要Control.Invoke?
- 6. 這是更快:SetEvent的話,SendMessage,PostMessage的
- 7. 爲什麼SendMessage()函數不起作用?
- 8. 發送不帶SendMessage和PostMessage的密鑰
- 9. 我的SendMessage/PostMessage部分代碼有什麼問題?
- 10. 爲什麼調度Event.OPEN而不是IOErrorEvent.IO_ERROR?
- 11. SendMessage()和PostMessage()正確的用法
- 12. C++ WINAPI:如何使用SendMessage/PostMessage WM_KEYDOWN lparam
- 13. 爲什麼SendMessage函數不及格
- 14. 爲什麼html5 postMessage不適合我?
- 15. 爲什麼調用「apply」而不是直接調用函數?
- 16. HTML 5中postMessage的用法是什麼?
- 17. 爲什麼=而不是:?
- 18. mfc - 帶自定義參數的sendmessage/postmessage
- 19. 如何在VB.NET中接收PostMessage/SendMessage?
- 20. 爲什麼我的DCOM客戶端鎖定對SendMessage的調用?
- 21. 爲什麼我們使用HTTP而不是遠程調用?
- 22. 爲什麼使用classmethod而不是staticmethod?
- 23. 爲什麼使用iconv_strpos而不是strpos?
- 24. 爲什麼使用registerDefaults:而不是setValue:forKey:?
- 25. 爲什麼使用TagBuilder而不是StringBuilder?
- 26. 爲什麼使用結構,而不是
- 27. 爲什麼使用StringWriter而不是StringBuffer?
- 28. 爲什麼使用s:Line而不是mx:HRule?
- 29. 爲什麼使用ImageIcon而不是Image?
- 30. 爲什麼使用SQLiteOpenHelper而不是SQLiteDatabase?
我認爲答案與PostMessage和SendMessage在接收端具有非常不同的行爲有關何時和如何處理消息(通過消息隊列或直接調用窗口過程)。由此可見,在兩者上都使用PostMessage。如果有人對此有良好的評價,請回答。 – MicroVirus
@Micro:跨線程SendMessage調用**從不**導致直接調用相應的窗口過程。雖然PostMessage和SendMessage在接收端的行爲不同,但不同之處在於,發送的跨線程消息由任何消息檢索函數自動分配,而發佈的消息通過調用'DispatchMessage'。 @paul:'SendMessage'不能返回,直到調用返回。如果UI線程阻塞,那麼也會阻塞調用線程。 'PostMessage'是防止死鎖的一種方法。 – IInspectable
@IInspectable但是當調用Control.Invoke()時,調用線程會等待,所以如果UI線程阻塞,這也會阻塞調用線程。 – paul