第一次通過CLR Profile解決內存占用過高的問題


炮哥:"嘿,哥們,忙啥呢,電腦卡成這逼樣。"

勇哥:"在用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#也有這個。”

炮哥:“所以說當你視野放開時,你會發現更多的美好。”

勇哥:“不扯了,該下班了。噢,對了,昨晚看了一部電影<美麗人生>,有興趣的話可以看下,很不錯。”

 


免責聲明!

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



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