用戶界面對象的線程親緣性: 設備上下文
設備上下文也有一定程度的線程親緣性。調用 DC 相關函數,例如 GetDC 的線程,必須在同一個線程中調用其對應的 ReleaseDC。但和窗口句柄一樣,在 DC 對象的生存期內,任何線程都可以訪問它。
如果你希望以多線程方式使用 DC,則負責協調該設備上下文的使用者,以便一次只有一個線程使用它。
例如,若要跨多個線程承載無窗口控件,主機在主線程上獲取 DC,然后按順序要求每個控件將自身繪制到該 DC 中。一次只有一個控件繪制到 DC 中,即使該控件恰好位于不同的線程上也是如此。
DC 的線程親緣性比窗口句柄的線程親緣性要微妙得多,因為如果你搞砸并從錯誤的線程釋放 DC,事情似乎仍然運行良好,但窗口管理器的內部資源記錄表會一團糟,你可能會在稍后從 GetDC 獲得一個無效的 DC 句柄,然后用戶界面會呈現出你所不希望看到的樣子,甚至會以應用程序的直接崩潰作為結局。
在下一篇文章中,我將介紹其他的用戶界面元素的線程親緣性,請拭目以待。
總結
復雜用戶界面開發起來需要花費一些功夫,在開發拓撲梅爾智慧辦公平臺(Topomel Box)的過程中,我總是遵循一個簡單的原則:僅在主界面線程中操控用戶界面對象,工作線程只用來干“臟活累活”。
有了這個統一的規則,你會形成肌肉記憶:這個更新界面的代碼應該放在哪里。
簡單,是一種美。