• 用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
     8                CounterCreationData totalPaint = new CounterCreationData();
     9                totalPaint.CounterName = "# operator executed";
    10                totalPaint.CounterHelp = "Counts of OnPaint events called";
    11                totalPaint.CounterType = PerformanceCounterType.NumberOfItems32;
    12
    13                ccdc.Add(totalPaint);
    14
    15                PerformanceCounterCategory.Create("GDI+ Monitor""Some counters for GDI+ objects", PerformanceCounterCategoryType.MultiInstance, ccdc);
    16            }

    17        }

    好,点一下button1之后,我们就可以在perfmon中看到GDI+ Monitor这个category了,然后只有一个counter,就是# operator executed

    然后在winform中增加这么一段:
               paintcall = new PerformanceCounter();
                paintcall.CategoryName 
    = "GDI+ Monitor";
                paintcall.CounterName 
    = "# operator executed";
                paintcall.MachineName 
    = ".";
                paintcall.ReadOnly 
    = false;

    好了,代码里面可以用paintcall这个变量了。我们现在的需求是监视Paint被触发了多少次,那么可以在代码中这么写:
     1            Graphics g2 = e.Graphics;
     2
     3            Bitmap bmp = new Bitmap(this.Width, this.Height);
     4            Graphics g = Graphics.FromImage(bmp);
     5
     6            paintcall.Increment();
     7
     8            Rectangle r = new Rectangle(00this.Width, this.Height);
     9            g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);
    10
    11            g2.DrawImage(bmp, new Point(00));
    12
    13            g.Dispose();
    14            g = null;
    15
    16            bmp.Dispose();
    17            bmp = null;

    看上面第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
     8        private void Form1_ResizeBegin(object sender, EventArgs e)
     9        {
    10            resize = true;
    11        }

    然后我们修改一下Paint事件的代码如下:
     1        private void Form1_Paint(object sender, PaintEventArgs e)
     2        {
     3            if (true == resize) return;
     4
     5            Graphics g2 = e.Graphics;
     6
     7            Bitmap bmp = new Bitmap(this.Width, this.Height);
     8            Graphics g = Graphics.FromImage(bmp);
     9
    10            paintcall.Increment();
    11
    12            Rectangle r = new Rectangle(00this.Width, this.Height);
    13            g.FillRectangle(new LinearGradientBrush(r, Color.Red, Color.Blue, LinearGradientMode.BackwardDiagonal), r);
    14
    15            g2.DrawImage(bmp, new Point(00));
    16
    17            g.Dispose();
    18            g = null;
    19
    20            bmp.Dispose();
    21            bmp = null;
    22        }

    注意第三行,我们判断,如果在resize过程中,那么就直接返回。这样,虽然界面像白板一样,但是却少了很多Paint操作,从性能上会好不少。
  • 相关阅读:
    USNews2018世界大学1250所排行榜
    2017年高盛“漂亮50”股票名单
    斯坦福纳米科学家崔屹:做顶级科研,还要开成功公司
    你的死工资正在拖垮你
    中国未来真正的30个商业模式
    一篇文看懂Hadoop:风雨十年,未来何去何从
    Lua常用API
    Cocos2d-x使用Luajit将Lua脚本编译为bytecode,从而实现加密
    初识Luajit
    如何在Windows平台使用VS搭建C++/Lua的开发环境
  • 原文地址:https://www.cnblogs.com/juqiang/p/958168.html
Copyright © 2020-2023  润新知