炮哥:"嘿,哥們,忙啥呢,電腦卡成這逼樣。"
勇哥:"在用CLR Profile工具分析下FlexiPrint的內存占用情況。"
炮哥:“哎喲,不錯啊,玩高級的了。”
勇哥:“也沒有啊,就是發現點擊查詢按鈕查詢數據時,如果數據量一大的話,內存上上升了好幾個M,所以第一感覺就不太正常。正好以前也了解過CLR Profile,但一直沒怎么具休的用過,這次正好拿來研究研究。”
炮哥:“Nice job,要向你學習,能夠主動發現問題並研究解決方法。對了,有什么發現么?”
勇哥:“通過工具發現dgMain_CellFormatting方法占用內存過多。”
炮哥:“這個方法干嘛用的,要這么多的內存?”
勇哥:“其實做的事情很簡單,根據每行訂單的不同狀態,顯示不同的圖標,以便讓客戶能夠很直白的了解訂單的狀態。”
炮哥:“噢,是這樣,那確實沒什么,讓我看下代碼。”
namespace IPP_PCL.HomeViewUserControl { public partial class PrintOrderInformationUserControl : UserControl, IHomePrintOrderInformationView { #region Field private readonly PrintCellLiteServiceClient _serviceClient = new PrintCellLiteServiceClient(); #endregion #region Event Handler /// <summary> /// 此事件主要用於圖片按鈕的顯示 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void dgMain_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { if (dgMain.Columns[e.ColumnIndex].Name.Equals("dgMain_PrintIcon")) { int row = e.RowIndex; //獲取展示圖片按鈕的單元格 string status = dgMain.Rows[row].Cells["dgMain_statusKey"].Value.ToString(); switch (status) { case "Print in Progress": string erpSoNumber = this.dgMain.Rows[row].Cells["dgMain_ErpSoNumber"].Value.ToString(); //從DB中查找erp_so_number的記錄 IEnumerable<FileIndexModel> fileIndexes = _serviceClient.GetFileIndex(erpSoNumber); //如果在FileIndex表中存在pro的記錄 if (fileIndexes == null || !fileIndexes.Any()) { break; } FileIndexModel fileIndex = fileIndexes.First(); if (FileStatus.PRINTED != fileIndex.PrintedStatus && FileStatus.PARTIAL_PRINTED != fileIndex.PrintedStatus) { e.Value = Properties.Resources.picYellow; } else { e.Value = Properties.Resources.picGreen; } break; case "Printed": e.Value = Properties.Resources.picGreen; break; case "Partial Printed": e.Value = Properties.Resources.picGreen; break; default: e.Value = Properties.Resources.picYellow; break; } } } #endregion } }
勇哥:“......”
炮哥:“很簡單,寫得很明白,這方法沒什么問題吧,會不會搞錯了。”
勇哥:“應該不會,通過CLR Profile分析發現,在這個方法中創建了非常多的對象。”
炮哥:“你是說BitMap對象?”
勇哥:“是的。”
炮哥:“噢,明白了,每次訪問Properties.Resources.picGreen類似的屬性時,都會創建一個新的對象。但其實圖標就那么幾類,完全可以先保存在內存中,要用時直接引用就行了。”
勇哥:“說得對,讓我修改下代碼 ,看看情況。”
炮哥:“讓我看下你怎么修改的?”
勇哥:“......”
1 namespace IPP_PCL.HomeViewUserControl 2 { 3 public partial class PrintOrderInformationUserControl : UserControl, IHomePrintOrderInformationView 4 { 5 #region Field 6 7 private readonly PrintCellLiteServiceClient _serviceClient = new PrintCellLiteServiceClient(); 8 9 Bitmap picGreenBitMap = Properties.Resources.picGreen; 10 11 Bitmap picYellowBitMap = Properties.Resources.picYellow; 12 13 #endregion 14 15 #region Ctor 16 17 public PrintOrderInformationUserControl() 18 { 19 InitializeComponent(); 20 } 21 22 #endregion 23 24 #region Event Handler 25 26 /// <summary> 27 /// 此事件主要用於圖片按鈕的顯示 28 /// </summary> 29 /// <param name="sender"></param> 30 /// <param name="e"></param> 31 private void dgMain_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) 32 { 33 if (dgMain.Columns[e.ColumnIndex].Name.Equals("dgMain_PrintIcon")) 34 { 35 int row = e.RowIndex; 36 //獲取展示圖片按鈕的單元格 37 string status = dgMain.Rows[row].Cells["dgMain_statusKey"].Value.ToString(); 38 39 switch (status) 40 { 41 case "Print in Progress": 42 43 var proDt = dgMain.DataSource as DataTable; 44 45 if (proDt == null || proDt.Rows.Count == 0) { break; } 46 47 string erpSoNumber = this.dgMain.Rows[row].Cells["dgMain_ErpSoNumber"].Value.ToString(); 48 49 //從DB中查找erp_so_number的記錄 50 IEnumerable<FileIndexModel> fileIndexes = _serviceClient.GetFileIndex(erpSoNumber); 51 52 //如果在FileIndex表中存在pro的記錄 53 if (fileIndexes == null || !fileIndexes.Any()) { break; } 54 55 FileIndexModel fileIndex = fileIndexes.First(); 56 57 if (FileStatus.PRINTED != fileIndex.PrintedStatus && FileStatus.PARTIAL_PRINTED != fileIndex.PrintedStatus) 58 { 59 e.Value = picYellowBitMap; 60 } 61 else 62 { 63 e.Value = picGreenBitMap; 64 } 65 66 break; 67 68 case "Printed": 69 70 e.Value = picGreenBitMap; 71 break; 72 73 case "Partial Printed": 74 75 e.Value = picGreenBitMap; 76 break; 77 78 default: 79 80 e.Value = picYellowBitMap; 81 break; 82 } 83 } 84 } 85 86 #endregion 87 88 } 89 }
炮哥:“再用CLR Profile分析下修改后的內存情況。”
勇哥:“你看,內存直接從9.0M變為425kB。”
炮哥:“哈哈,看來問題已經解決了。”
勇哥:“今天我發現C#也有閉包的概念。”
炮哥:“閉包?什么玩意?”
勇哥:“我是在學習JS的時候發現有閉包這個概念,但是沒想到C#也有這個。”
炮哥:“所以說當你視野放開時,你會發現更多的美好。”
勇哥:“不扯了,該下班了。噢,對了,昨晚看了一部電影<美麗人生>,有興趣的話可以看下,很不錯。”