C#.NET,技巧篇(DataGridView線程操作)


這個系列的文章,主要是平時做C#.NET(Framework 3.5)開發的時候,積累的經驗和技巧。我們平時總有這樣的體會,遇到一個特別難解決的問題,網上尋它千百度也沒能搜索到有用的信息。這時你肯定會想,解決了這個問題一定要記下來。實際上待你埋頭苦干終於搞定它的時候,往往被喜悅和成就感充斥,再加上這個問題本身解決的方法可能簡單無比,於是忘記去記錄下來。本篇就從零開始,回顧五年編程經驗積累的各種奇葩問題的解決方法。

 

DataGridView是個神奇的控件,與數據集綁定顯示,方便、耐用。但是這樣一個封裝了99%內部實現的控件,必然會出現你讓你抓狂的異常。

來看今天遇到的問題:主窗口有一個DataGridView控件,它的DataSource是atable;在線程中獲取一行數據arow,添加到atable中,然后invoke主線程去修改MainForm上一個Label的Text。線程函數代碼如下:

threadfun()
{
	//......

	atable.AddRow(arow);

	Invoke(adelegate);

	//......
}

 

測試exe程序的時候出現主界面無響應的情況,反復重啟發現每當添加第N條數據后問題出現,N是某個定值。使用VS調試源代碼,問題消失。

做C#開發最難受的情況就是,VS調試一切OK,運行exe出錯。這種情況我們以后會經常遇到,可以理解為.Net Framework的運行時和調試時是略有不同的,不再深入追究。使用VS附加進程調試,找到源頭是invoke的委托代碼執行被掛起,導致主界面無響應。

 

解決方法:在線程中,對DataGridView的數據源進行的操作都使用委托。

分析:數據表atable是DataGridView的數據源,DataGridView是主線程的控件,雖然在線程函數里可以訪問同一命名空間下的引用,但是一旦牽扯到控件,最好還是讓主線程去操作,否則就會出現各種意想不到的問題,比如今天遇到的。

刨根問底:向atable添加一行arow,這會導致DataGridView重繪,因為綁定的數據源自動顯示。從這個角度來看,今天的例子犯了一個常見的錯誤:從線程修改主線程控件。特殊的地方是這個重繪操作是.Net內部通過某種機制實現的,它並不違反約束,前N-1次操作並沒有異常發生就能看出來。那么,為什么第N次添加操作就一定會觸發這個問題呢?

真相:通過觀察視圖設計,我發現第N條數據會使DataGridView自動添加縱向滾動條,為了驗證這是否是真相,我減小了DataGridView的高度,果然小於第N條數據就出現了問題,從而確定就是這個添加滾動條的動作導致主線程掛起,窗口無響應。

總結:想弄明白這個問題的最終答案,必須完全理解DataGridView的內部實現機制,這個機制允許從線程向DataGridView添加行並顯示,但是當自動創建滾動條的時候會掛起,我想這也算是一個bug了吧。從我們開發者自身角度來講,保持一個良好的編程習慣至關重要——線程不訪問其他線程的變量,必須訪問的時候所有操作都用委托。如果上述例子的開發者能遵循這個原則,就不會遇到這個難題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM