用perfmon简单分析GDI+性能和代码的一点小改进
Paint事件被触发了多少次?比较简单的方式,我们自己做一个perfmon能用的counter。看代码:
1
private void button1_Click(object sender, EventArgs e)
2
{
3
4
if (!PerformanceCounterCategory.Exists("GDI+ Monitor"))
5
{
6
CounterCreationDataCollection ccdc = new CounterCreationDataCollection();
7![](/Images/OutliningIndicators/InBlock.gif)
8
CounterCreationData totalPaint = new CounterCreationData();
9
totalPaint.CounterName = "# operator executed";
10
totalPaint.CounterHelp = "Counts of OnPaint events called";
11
totalPaint.CounterType = PerformanceCounterType.NumberOfItems32;
12![](/Images/OutliningIndicators/InBlock.gif)
13
ccdc.Add(totalPaint);
14![](/Images/OutliningIndicators/InBlock.gif)
15
PerformanceCounterCategory.Create("GDI+ Monitor", "Some counters for GDI+ objects", PerformanceCounterCategoryType.MultiInstance, ccdc);
16
}
17
}
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/InBlock.gif)
5
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
6
![](/Images/OutliningIndicators/InBlock.gif)
7
![](/Images/OutliningIndicators/InBlock.gif)
8
![](/Images/OutliningIndicators/InBlock.gif)
9
![](/Images/OutliningIndicators/InBlock.gif)
10
![](/Images/OutliningIndicators/InBlock.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
17
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
好,点一下button1之后,我们就可以在perfmon中看到GDI+ Monitor这个category了,然后只有一个counter,就是# operator executed
然后在winform中增加这么一段:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
好了,代码里面可以用paintcall这个变量了。我们现在的需求是监视Paint被触发了多少次,那么可以在代码中这么写:
1
Graphics g2 = e.Graphics;
2![](/Images/OutliningIndicators/None.gif)
3
Bitmap bmp = new Bitmap(this.Width, this.Height);
4
Graphics g = Graphics.FromImage(bmp);
5![](/Images/OutliningIndicators/None.gif)
6
paintcall.Increment();
7![](/Images/OutliningIndicators/None.gif)
8
Rectangle r = new Rectangle(0, 0, this.Width, this.Height);
9
g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);
10![](/Images/OutliningIndicators/None.gif)
11
g2.DrawImage(bmp, new Point(0, 0));
12![](/Images/OutliningIndicators/None.gif)
13
g.Dispose();
14
g = null;
15![](/Images/OutliningIndicators/None.gif)
16
bmp.Dispose();
17
bmp = null;
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/None.gif)
3
![](/Images/OutliningIndicators/None.gif)
4
![](/Images/OutliningIndicators/None.gif)
5
![](/Images/OutliningIndicators/None.gif)
6
![](/Images/OutliningIndicators/None.gif)
7
![](/Images/OutliningIndicators/None.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/None.gif)
10
![](/Images/OutliningIndicators/None.gif)
11
![](/Images/OutliningIndicators/None.gif)
12
![](/Images/OutliningIndicators/None.gif)
13
![](/Images/OutliningIndicators/None.gif)
14
![](/Images/OutliningIndicators/None.gif)
15
![](/Images/OutliningIndicators/None.gif)
16
![](/Images/OutliningIndicators/None.gif)
17
![](/Images/OutliningIndicators/None.gif)
看上面第6行,这句会把paint call增加一。当然,其他方法有很多,这里不写了。
好,跑一下perfmon,然后把我们新增加的counter add上,嗯,可以看到当窗口无效的时候,计数器就增加了。
有一个小的细节,当窗口稍微改动大小的时候,你会发现Paint被调用了多次,这个实在很郁闷。so,稍微做点手脚:
1
private bool resize = false;
2
private void Form1_ResizeEnd(object sender, EventArgs e)
3
{
4
resize = false;
5
this.Invalidate();
6
}
7![](/Images/OutliningIndicators/None.gif)
8
private void Form1_ResizeBegin(object sender, EventArgs e)
9
{
10
resize = true;
11
}
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/None.gif)
3
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
4
![](/Images/OutliningIndicators/InBlock.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
7
![](/Images/OutliningIndicators/None.gif)
8
![](/Images/OutliningIndicators/None.gif)
9
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
10
![](/Images/OutliningIndicators/InBlock.gif)
11
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
然后我们修改一下Paint事件的代码如下:
1
private void Form1_Paint(object sender, PaintEventArgs e)
2
{
3
if (true == resize) return;
4![](/Images/OutliningIndicators/InBlock.gif)
5
Graphics g2 = e.Graphics;
6![](/Images/OutliningIndicators/InBlock.gif)
7
Bitmap bmp = new Bitmap(this.Width, this.Height);
8
Graphics g = Graphics.FromImage(bmp);
9![](/Images/OutliningIndicators/InBlock.gif)
10
paintcall.Increment();
11![](/Images/OutliningIndicators/InBlock.gif)
12
Rectangle r = new Rectangle(0, 0, this.Width, this.Height);
13
g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);
14![](/Images/OutliningIndicators/InBlock.gif)
15
g2.DrawImage(bmp, new Point(0, 0));
16![](/Images/OutliningIndicators/InBlock.gif)
17
g.Dispose();
18
g = null;
19![](/Images/OutliningIndicators/InBlock.gif)
20
bmp.Dispose();
21
bmp = null;
22
}
![](/Images/OutliningIndicators/None.gif)
2
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](/Images/OutliningIndicators/InBlock.gif)
4
![](/Images/OutliningIndicators/InBlock.gif)
5
![](/Images/OutliningIndicators/InBlock.gif)
6
![](/Images/OutliningIndicators/InBlock.gif)
7
![](/Images/OutliningIndicators/InBlock.gif)
8
![](/Images/OutliningIndicators/InBlock.gif)
9
![](/Images/OutliningIndicators/InBlock.gif)
10
![](/Images/OutliningIndicators/InBlock.gif)
11
![](/Images/OutliningIndicators/InBlock.gif)
12
![](/Images/OutliningIndicators/InBlock.gif)
13
![](/Images/OutliningIndicators/InBlock.gif)
14
![](/Images/OutliningIndicators/InBlock.gif)
15
![](/Images/OutliningIndicators/InBlock.gif)
16
![](/Images/OutliningIndicators/InBlock.gif)
17
![](/Images/OutliningIndicators/InBlock.gif)
18
![](/Images/OutliningIndicators/InBlock.gif)
19
![](/Images/OutliningIndicators/InBlock.gif)
20
![](/Images/OutliningIndicators/InBlock.gif)
21
![](/Images/OutliningIndicators/InBlock.gif)
22
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
注意第三行,我们判断,如果在resize过程中,那么就直接返回。这样,虽然界面像白板一样,但是却少了很多Paint操作,从性能上会好不少。