+ -
当前位置:首页 → 问答吧 → C# PictureBox 画图占用CPU

C# PictureBox 画图占用CPU

时间:2011-12-15

来源:互联网

问题:绘画一条由10000个数据(x,y)组成的曲线,现在PictureBox_Paint使用e.graphics,占用超高的CPU!

求解决方法。

作者: spade24   发布时间: 2011-12-15

作者: spade24   发布时间: 2011-12-15

应该不会吧,上你的代码看看

作者: wangsunjun   发布时间: 2011-12-15

引用 2 楼 wangsunjun 的回复:

应该不会吧,上你的代码看看



C# code

for(int i=0;i<10000;i++)
{
   e.Graphics.DrawLine(new Pen(Color.Red, 1), fX0[i], fY0[i], fX1[i+1], fY1[i+1]);
}



多了这段代码,CPU占用率会提高到50。

作者: spade24   发布时间: 2011-12-15

明白了,PictureBox.Paint事件是怎么说的 occurs when the control is redrawn

也就是说你每在这个控件上画一个点时,就会执行一个paint事件
这样你一个事件里有10000次循环,CPU会受不了的

你直接在窗体上画呗,把窗体拖大点,为什么要用PictureBox

作者: wangsunjun   发布时间: 2011-12-15

引用 4 楼 wangsunjun 的回复:

明白了,PictureBox.Paint事件是怎么说的 occurs when the control is redrawn

也就是说你每在这个控件上画一个点时,就会执行一个paint事件
这样你一个事件里有10000次循环,CPU会受不了的

你直接在窗体上画呗,把窗体拖大点,为什么要用PictureBox


你意思是直接用form_paint?form里面有其他控件,是不是要考虑控件布局对绘图位置的影响?还有,在form_paint里绘画的图形,会被其它控件覆盖,如何解决呢?

作者: spade24   发布时间: 2011-12-15

我上面的说法可能说错了

我理解成了用GDI+画东西的时候,,不在Paint事件中是否可行,我也不太清楚了
不过貌似用Pen好像可以的,,记不清了
你那个循环10000次的代码,可以把new Pen(Color.Red,1)放到循环外面去,每次都用外面实例化的对象,没必要每次 循环都要实例化一个

不用PictureBox,你要考虑画的点的坐标问题了,,不要画在其它控件所在区域就行

作者: wangsunjun   发布时间: 2011-12-15

是的,验证了下,在什么控件上画东西,GDI+必须把画的代码写在Paint事件里
用 Graphics g = e.Graphics; 的g来,Draw~~~~~

那我4楼的说法是错的 抱歉撒
private void Form1_Paint(object sender, PaintEventArgs e)
  {
  Graphics g = e.Graphics; //创建画板,这里的画板是由Form提供的.
  Pen p = new Pen(Color.Blue, 2);//定义了一个蓝色,宽度为的画笔
  g.DrawLine(p, 10, 10, 100, 100);//在画板上画直线,起始坐标为(10,10),终点坐标为(100,100)
  g.DrawRectangle(p, 10, 10, 100, 100);//在画板上画矩形,起始坐标为(10,10),宽为,高为
  g.DrawEllipse(p, 10, 10, 100, 100);//在画板上画椭圆,起始坐标为(10,10),外接矩形的宽为,高为
  }
这是别人的代码,,参考下
地址:http://www.cnblogs.com/stg609/archive/2008/03/16/1108333.html

作者: wangsunjun   发布时间: 2011-12-15

引用 6 楼 wangsunjun 的回复:

我上面的说法可能说错了

我理解成了用GDI+画东西的时候,,不在Paint事件中是否可行,我也不太清楚了
不过貌似用Pen好像可以的,,记不清了
你那个循环10000次的代码,可以把new Pen(Color.Red,1)放到循环外面去,每次都用外面实例化的对象,没必要每次 循环都要实例化一个

不用PictureBox,你要考虑画的点的坐标问题了,,不要画在其它控件所在区域就行
……


1、上面代码中“new Pen(Color.Red,1)”在实际程序中鉴于统一管理肯定是放在外面,当然,直接这样new,程序消耗的也只是内存,不会占用太多的CPU;

2、使用PictureBox的目的就是为了在form大范围区域中方便我们控制其中一个控件上的绘图,反之直接在form中paint,要去控制会不会很费劲,难以把握。

作者: spade24   发布时间: 2011-12-15

C# code


        private void button1_Click(object sender, EventArgs e)
        {
            Graphics c = CreateGraphics();
            Random rnd = new Random();
            for (int i = 0; i < 100000; i++)
            {
                int fx0 = rnd.Next(30);
                int fy0 = rnd.Next(30);
                int fx1 = rnd.Next(400);
                int fy2 = rnd.Next(400);                
                c.DrawLine(new Pen(Color.Red, 1), fx0, fy0, fx1, fy2);
            }
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Random rnd = new Random();
            for (int i = 0; i < 10000; i++)
            {
                int fx0 = rnd.Next(30);
                int fy0 = rnd.Next(30);
                int fx1 = rnd.Next(400);
                int fy2 = rnd.Next(400);

                e.Graphics.DrawLine(new Pen(Color.Red, 1), fx0, fy0, fx1, fy2);
            }
        }


测试到10w都没有问题,cpu正常的很,

作者: wukaiping870123   发布时间: 2011-12-15

引用 7 楼 wangsunjun 的回复:

是的,验证了下,在什么控件上画东西,GDI+必须把画的代码写在Paint事件里
用 Graphics g = e.Graphics; 的g来,Draw~~~~~

那我4楼的说法是错的 抱歉撒
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.G……


鉴于form中还有其它一些控件(并且为了适用不同分辨率的电脑显示,所有控件的dock都是fill),如何解决form_Paint中绘画出来的图形被覆盖的问题?

作者: spade24   发布时间: 2011-12-15

引用 9 楼 wukaiping870123 的回复:

C# code
private void button1_Click(object sender, EventArgs e)
{
Graphics c = CreateGraphics();
Random rnd = new Random();
for (int i = 0; i < 100000; i++)
{
int fx0 = rnd.Next(30);
int fy0 = rnd.Next(30);
int fx1 = rnd.Next(400);
int fy2 = rnd.Next(400);
c.DrawLine(new Pen(Color.Red, 1), fx0, fy0, fx1, fy2);
}
}



你确认在执行这个事件后,CPU没变化?查看任务管理器得到:CPU上升95以上,电脑处于假死!!

作者: spade24   发布时间: 2011-12-15

打断点让画图中断,看CPU是不是恢复了??如果没恢复再去掉断点再画,看看是不是又很 大了???

作者: wangsunjun   发布时间: 2011-12-15

引用 12 楼 wangsunjun 的回复:

打断点让画图中断,看CPU是不是恢复了??如果没恢复再去掉断点再画,看看是不是又很 大了???


不用打断点,打开任务管理器,执行事件观察任务管理器的CPU就OK啊。
如果是断点,到断点后程序相当于已经停止!

作者: spade24   发布时间: 2011-12-15

程序中绘图的部分是需要实时连续执行。这个可能是我前面忘记说明。

作者: spade24   发布时间: 2011-12-15

这种频繁的画图代码放在Form1_Paint中又会频繁调用,所以cpu会飙上去。c#本身画图就比较费cpu的。
我不太清楚lz的需求,我觉得是不是可以不在Form1_Paint事件中绘图,而是直接在内存中绘制一个image对象,然后把它的图片赋给界面控件。

作者: wangyue4   发布时间: 2011-12-15

引用 15 楼 wangyue4 的回复:

这种频繁的画图代码放在Form1_Paint中又会频繁调用,所以cpu会飙上去。c#本身画图就比较费cpu的。
我不太清楚lz的需求,我觉得是不是可以不在Form1_Paint事件中绘图,而是直接在内存中绘制一个image对象,然后把它的图片赋给界面控件。


1、是用PictureBox_Paint,不是Form1_Paint哦!
2、尝试过你说的通过内存绘制image,但这样画出来的图形很粗糙,效果不是很好。

作者: spade24   发布时间: 2011-12-15

你在内存画和在界面画是一样的啊,都是用的gdi啊,怎么会有区别呢

作者: wangyue4   发布时间: 2011-12-15

首先不要在循环里面去初始化一个变量,还初始化10000次。
你这个每画一次都要进paint时间。不如把10000个数据放在一个数组里面,用那个画多点的方法画出来就可以吧。具体什么太久没用忘记了,呵呵。

作者: zdzcool   发布时间: 2011-12-15

引用 11 楼 spade24 的回复:

引用 9 楼 wukaiping870123 的回复:

C# code
private void button1_Click(object sender, EventArgs e)
{
Graphics c = CreateGraphics();
Random rnd = new Random();
for (int i = 0; i < 100000; i++)
{
int……

没有,真没有明显的变化,是不是你数组造成的瓶颈???

作者: wukaiping870123   发布时间: 2011-12-15

引用 17 楼 wangyue4 的回复:

你在内存画和在界面画是一样的啊,都是用的gdi啊,怎么会有区别呢


1、刚才再次验证了一下,使用内存到iamge出来的图形比e.Graphics的图形粗糙,或者是我哪里写得不对,代码如下:
C# code

Image imageFile = new Bitmap(100, 100);
Graphics newGraphics = Graphics.FromImage(imageFile);
newGraphics.DrawString("ABCDEFG", font2, Brushes.Black, 0, 0);
e.Graphics.DrawImage(imageFile, 200, 200, 100, 200);
newGraphics.Dispose(); 



2、经过同样的验证,使用内存画似乎仍然没有解决关键问题,就是占用超高CPU,代码如下:
C# code

Image imageFile = new Bitmap(100, 100);
Graphics newGraphics = Graphics.FromImage(imageFile);
for (int i = 0; i < 10000;i++ )
{
    e.Graphics.DrawLine(pen5, 10, 10, 100, 100);
}
e.Graphics.DrawImage(imageFile, 200, 200, 100, 200);
newGraphics.Dispose(); 

作者: spade24   发布时间: 2011-12-15

引用 20 楼 spade24 的回复:

引用 17 楼 wangyue4 的回复:

你在内存画和在界面画是一样的啊,都是用的gdi啊,怎么会有区别呢


1、刚才再次验证了一下,使用内存到iamge出来的图形比e.Graphics的图形粗糙,或者是我哪里写得不对,代码如下:
C# code

Image imageFile = new Bitmap(100, 100);
Graphics newGraphics = G……

抱歉,我的CPU是四核的,所以不明显,单核的确占用明显.

作者: wukaiping870123   发布时间: 2011-12-15

引用 19 楼 wukaiping870123 的回复:

没有,真没有明显的变化,是不是你数组造成的瓶颈???


一模一样的代码:
C# code

        private void button1_Click(object sender, EventArgs e)
        {
            Graphics c = CreateGraphics();
            Random rnd = new Random();
            for (int i = 0; i < 100000; i++)
            {
                int fx0 = rnd.Next(30);
                int fy0 = rnd.Next(30);
                int fx1 = rnd.Next(400);
                int fy2 = rnd.Next(400);                
                c.DrawLine(new Pen(Color.Red, 1), fx0, fy0, fx1, fy2);
            }
        }




你说的没有明显变化,是通过什么方式验证的?

作者: spade24   发布时间: 2011-12-15

C# code
 Image img = new Bitmap(400, 400);

            //Graphics c = CreateGraphics();
            Graphics c = Graphics.FromImage(img);
            Random rnd = new Random();
            for (int i = 0; i < 1000; i++)
            {
                int fx0 = rnd.Next(30);
                int fy0 = rnd.Next(30);
                int fx1 = rnd.Next(400);
                int fy2 = rnd.Next(400);
                c.DrawLine(new Pen(Color.Red, 1), fx0, fy0, fx1, fy2);                
            }
            c.Dispose();
            pictureBox1.Image = img;

作者: wukaiping870123   发布时间: 2011-12-15

热门下载

更多