用戶界面對(duì)象的線程親緣性: 設(shè)備上下文
設(shè)備上下文也有一定程度的線程親緣性。調(diào)用 DC 相關(guān)函數(shù),例如 GetDC 的線程,必須在同一個(gè)線程中調(diào)用其對(duì)應(yīng)的 ReleaseDC。但和窗口句柄一樣,在 DC 對(duì)象的生存期內(nèi),任何線程都可以訪問它。
如果你希望以多線程方式使用 DC,則負(fù)責(zé)協(xié)調(diào)該設(shè)備上下文的使用者,以便一次只有一個(gè)線程使用它。
例如,若要跨多個(gè)線程承載無窗口控件,主機(jī)在主線程上獲取 DC,然后按順序要求每個(gè)控件將自身繪制到該 DC 中。一次只有一個(gè)控件繪制到 DC 中,即使該控件恰好位于不同的線程上也是如此。
DC 的線程親緣性比窗口句柄的線程親緣性要微妙得多,因?yàn)槿绻愀阍也腻e(cuò)誤的線程釋放 DC,事情似乎仍然運(yùn)行良好,但窗口管理器的內(nèi)部資源記錄表會(huì)一團(tuán)糟,你可能會(huì)在稍后從 GetDC 獲得一個(gè)無效的 DC 句柄,然后用戶界面會(huì)呈現(xiàn)出你所不希望看到的樣子,甚至?xí)詰?yīng)用程序的直接崩潰作為結(jié)局。
在下一篇文章中,我將介紹其他的用戶界面元素的線程親緣性,請(qǐng)拭目以待。
總結(jié)
復(fù)雜用戶界面開發(fā)起來需要花費(fèi)一些功夫,在開發(fā)拓?fù)涿窢栔腔坜k公平臺(tái)(Topomel Box)的過程中,我總是遵循一個(gè)簡單的原則:僅在主界面線程中操控用戶界面對(duì)象,工作線程只用來干“臟活累活”。
有了這個(gè)統(tǒng)一的規(guī)則,你會(huì)形成肌肉記憶:這個(gè)更新界面的代碼應(yīng)該放在哪里。
簡單,是一種美。