MFC中CTreeCtrl加載節點緩慢的分析和解決方法

問題描述:最近解決了一個tree view插入節點緩慢的問題。原數據有1w多個節點,加載數據需要大概5s,導致整個UI掛起,處於hang up的狀態。查詢了很多資料,大概有幾種解決方案。


1. 使用virtual tree技術。

所謂虛擬樹,就是在插入節點的時候,並不是真正的載入節點中需要顯示的文本,而只是指明節點存在,在需要顯示節點的時候,響應treectrl的TVN_GETDISPINFO的notification,再加載需要顯示的文本。這樣可以提高插入節點的效率。如果節點層次較多,可以結合下面的方法2。


參考資料如下:http://www.codeguru.com/cpp/cpp/cpp_mfc/callbacks/article.php/c16667/How-to-make-a-virtual-tree-control--really-virtual.htm


缺點:但這種方法有個缺陷,由於並沒有真正的載入節點的文本,在響應treectrl的OnKeyDown方法時,無法通過按下的鍵值(如"A")定位到要找到的節點(如找到文本以A開頭的節點)。


2.延遲加載。

一個基本的方法是,並不是一次性的插入所有的節點,例如只插入幾個關鍵的節點並使之collapsed,在expand該節點的時候,通過響應TVN_ITEMEXPANDING再插入該節點下的子節點。或者創建一個Timer或者thread,延遲插入節點。


缺點:這種方法需要用戶更多的操作,如展開節點,等待節點的插入等等。影響用戶的體驗。


3.通過trace代碼,發現導致treectrl插入節點緩慢的原因是InsertItem的調用。在插入1w多個節點的時候,大概有300個節點的插入在調用InsertItem上耗費了時間(大概每調用30次左右就會耗費時間),每次調用的耗費大約爲15ms,累計爲4--5s。應該是InsertItem的調用會導致treectrl控件的重繪,而繪製控件會佔用其中大部分的時間。


解決方法是,在集中InsertItem之前調用treectrl的SetRedraw(FALSE),阻止treectrl的重繪,在插入節點完畢後,調用SetRedraw()恢復treectrl的重繪。

經測試,耗費的時間降到大概1s左右。

(注:由於此次的樹節點只有兩層,該方法是否對於多層次的樹節點有效,有待查證。)


參考資料如下:http://www.codeproject.com/Articles/696/Speeding-up-the-tree-control


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章