Laden...

Hohe CPU-Auslastung mit GDI+ reduzieren

Erstellt von woiperdinger vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.395 Views
W
woiperdinger Themenstarter:in
22 Beiträge seit 2010
vor 12 Jahren
Hohe CPU-Auslastung mit GDI+ reduzieren

Hallo, ich hoffe ich hab kein Thema übersehen das meine Frage beantwortet.
Und zwar zeichne ich mit Windows Forms was die CPU sehr schnell in die Höhe treibt.


    public partial class Form1 : Form
    {
        private Timer timer = new Timer();
        private Brush brushBlue = new SolidBrush(Color.Blue);
        private Brush brushRed = new SolidBrush(Color.Red);
        private Pen pen = new Pen(Color.Black, 1);
        private Bitmap bmp = new Bitmap(900, 900);
        private Graphics g;
        private bool toggle;

        public Form1()
        {
            InitializeComponent();
    
            this.pictureBox1.Image = this.bmp;
            this.g = Graphics.FromImage(this.bmp);
            this.timer.Interval = 200;
            this.timer.Tick += new EventHandler(timer_Tick);
            this.timer.Start();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            Brush brush = this.toggle ? this.brushBlue : this.brushRed;
            this.toggle = !this.toggle;

            for (int x = 0; x < 30; x++)
            {
                for (int y = 0; y < 30; y++)
                {
                    Rectangle rec = new Rectangle(x * 30, y * 30, 30, 30);
                    this.g.FillEllipse(brush, rec);
                    this.g.DrawEllipse(this.pen, rec);
                }
            }
            this.pictureBox1.Invalidate();
        }
    }

Allein hier wird mein Rechner (DUO Core 2.33 GHz und 3GB Ram) mit 10 Prozent beansprucht.
Verlagert man die Zeichenroutine in ein UserControl mit überschriebener OnPaint-Methode sind es immer noch ca. 7%.
Gibt es irgendwelche Tricks/Tips um die CPU-Last beim Zeichnen zu reduzieren?

1.130 Beiträge seit 2007
vor 12 Jahren

Gibt es irgendwelche Tricks/Tips um die CPU-Last beim Zeichnen zu reduzieren?

Winforms is halt viel Softwarerendering, nimm WPF für die GPU oder reduziere deine Gui soweit wie möglich...

Außerdem solltest du vermeiden, auf ein Bitmap zu zeichnen. Pictureboxen sind nicht zum Zeichnen!!

Projekte:Jade, HttpSaver
Zum Rechtschreiben gibts doch schon die Politiker. Aber die bauen auch nur mist!

5.742 Beiträge seit 2007
vor 12 Jahren

Außerdem solltest du vermeiden, auf ein Bitmap zu zeichnen. Pictureboxen sind nicht zum Zeichnen!!

Bzw. schon auf Bitmaps zeichnen, aber diese dann nicht in einer Picturebox darstellen.

Ein Graphics solltest du übrigens auch so schnell wie möglich wieder disposen.

Siehe auch [Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox).

Hinweis von herbivore vor 12 Jahren

Ein Graphics solltest du übrigens auch so schnell wie möglich wieder disposen.

Zur Klarstellung: Dass gilt nur für selbst erstellte (z.B. Graphics.FormImage) und nicht mehr benötigte Graphics-Objekte. Graphics-Objekte, die man übergeben bekommst, z.B. in den PaintEventArgs, darf man dagegen nicht zerstören.

W
woiperdinger Themenstarter:in
22 Beiträge seit 2010
vor 12 Jahren

WPF wäre auch meine 1. Wahl gewesen.
Das Projekt wurde ursprünglich für einen anderen Zweck entwickelt wo die CPU-Last zu vernachlässigen war.
Es war für eine Web-Applikation gedacht bei der serverseitig ein Bitmap generiert wurde das sich der Client dann zyklich mittels jQuery abholt.
Darum auch das Zeichnen ins Bitmap.
Das Projekt wird auch für Windows CE benötigt.
Da es dort kein Double Buffering gibt würde ich beim Zeichnen in ein UserControl mit Flackern rechnen.

Unter CE gibt es kein BackgroundImage für Form oder UserControl. Darum der Ansatz über die Picturebox.
Welche Alternativen hätte ich zur Picturebox die auch unter CE verwandbar sind?

Normal würde ich auch das Graphics möglichst schnell disposen.
Allerdings zeichne ich immer ins selbe Bitmap.
D.h. ich müsste mir alle 200ms ein neues Graphics erzeugen.
Ist es da nicht sinnvoller eine Reverenz zu behalten?

C
1.214 Beiträge seit 2006
vor 12 Jahren

Warum willst du das alles 200 ms umschalten? Wenn du das in der OnPaint Methode aufrufst, rufst du dann immer noch Invalidate auf?
Generell ist GDI+ natürlich schon langsam und für Animationen ziemlich ungeeignet. Aber ich habe damit auch schon ziemlich aufwändige Sachen gemacht, wenn man das schlau anstellt, kann man damit durchaus angenehm arbeiten.
Bist du sicher, dass du 900 Rechtecke zeichnen wilst? Die überlappen sich ja eh, wenn ich das richtig verstehe.

W
woiperdinger Themenstarter:in
22 Beiträge seit 2010
vor 12 Jahren

Nein, beim Ansatz über ein Usercontrol würde nur mein Timer Invalidate aufrufen um OnPaint anzustoßen.

Der Code war nur ein kleines Beispiel.
Im Projekt gibt es Animationen wie Farbänderung, Rotation, Bewegung... die zum Teil eine Intervallzeit haben.
Diese können auch bei 200ms liegen.
Der einfachste Weg für mich ist dann alles komplett neu zu zeichnen.
Die Shapes können z.B. eine Eltern-Kind-Beziehung haben bei der das Kindelement am Rand des Elternelements geclippt wird....
Das wäre ziemlich aufwändig da alles zu berücksichtigen.
Was ist z.B. wenn sich ein Element verschiebt, sich aber eine Z-Ebene drüber noch Elemente befinden...

C
1.214 Beiträge seit 2006
vor 12 Jahren

Ok, das hört sich dann zu rechenintensiv für GDI+ an... Das wirst du flüssig wohl nicht hinbekommen.

W
woiperdinger Themenstarter:in
22 Beiträge seit 2010
vor 12 Jahren

Ok, dann trotzdem danke fürs Lesen bzw. Antworten.
Ich hab gehofft es gibt noch irgendwelche Stellschrauben die ich bis jetzt nicht gefunden habe.