CLR Profile解决内存占用过高

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#也有这个。”

炮哥:“所以说当你视野放开时,你会发现更多的美好。”

勇哥:“不扯了,该下班了。噢,对了,昨晚看了一部电影<美丽人生>,有兴趣的话可以看下,很不错。”

原文地址:https://www.cnblogs.com/Leo_wl/p/5134710.html