CPU-Auslastung in C# ermitteln

Der nachfolgende Programmcode demonstriert, wie mit C# die Prozessorauslastung ermittelt und in einer Konsolenanwendung ausgegeben werden kann (funktioniert natürlich auch in einem Windows-Programm). Benötigt werden u.a. die Namespaces System.Diagnostics für die Klasse PerformanceCounter und System.Threading für die Thread-Klasse.

class CpuPerformance
{
        static void Main(string[] args)
        {
            PerformanceCounter processorPerformance =
                new PerformanceCounter(„Processor“, „% Processor Time“, „_Total“);
            Console.Clear();
            Console.Write(„CPU-Auslastung in %:“);
            int i = 0;
            while (i < 50)
            {
                Console.SetCursorPosition(22, 0);
                Console.Write(„{0,10:0.000}“,processorPerformance.NextValue());
                i++;
                Thread.Sleep(1000);
            }
        }
}

image 

Da man heute nicht mehr jedermann mit einer Konsolenanwendung zufrieden stellen kann, folgt auch noch ein Beispiel für ein Windows Forms Programm. Hierbei wird eine Progressbar zur Darstellung der CPU-Auslastung verwendet.

image

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;

namespace WinPerformanceInfo
{
    public partial class Form1 : Form
    {
        PerformanceCounter processorPerformance;
        bool isRunning;

        public Form1()
        {
            InitializeComponent();
            InitializeBackgroundWorker();
            processorPerformance =
              new PerformanceCounter(„Processor“,
                 „% Processor Time“, „_Total“);
            isRunning = false;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            btnStart.Enabled = false;
            btnStop.Enabled = true;
            isRunning = true;
            bgwCpu.RunWorkerAsync();
        }

        private void InitializeBackgroundWorker()
        {

            bgwCpu.DoWork += new DoWorkEventHandler
               (bgwCpu_DoWork);

            bgwCpu.ProgressChanged += new ProgressChangedEventHandler
               (bgwCpu_ProgressChanged);

            bgwCpu.WorkerReportsProgress = true;
            bgwCpu.WorkerSupportsCancellation = true;
        }

        private void bgwCpu_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbCpu.Value = e.ProgressPercentage;
        }

        private void bgwCpu_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            consumingMethod(worker, e);
        }

        void consumingMethod(BackgroundWorker worker, DoWorkEventArgs e)
        {
            if (worker.CancellationPending == true)
                return;
            while (isRunning)
            {
                worker.ReportProgress((int)processorPerformance.NextValue());
                Thread.Sleep(1000);
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            bgwCpu.CancelAsync();
            btnStop.Enabled = false;
            btnStart.Enabled = true;
            isRunning = false;
        }
    }
}

BackgroundWorker mit Windows Forms (C#)

Bei der Programmierung von Windows Anwendungen mit Windows Forms, unterstützt die BackgroundWorker Klasse den Programmierer bei der Erstellung von Anwendungen bei denen das User Interface auch weiterhin funktioniert.

Sicher kennen die meisten die Situation, das eine Anwendung beim Aufruf einer rechen- und damit meist zeitintensiven Operation, das Programm nur noch die Sanduhr zeigt und nicht mehr reagiert, solange bis die Operation abgeschlossen ist. Hier hilft die BackgroundWorker Klasse ab dem .NET Framework 2 weiter, indem die Ausführung der Operation in einem eigenen dedizierten Thread erfolgt.

Der BackgroundWorker lässt sich sowohl programmatisch erzeugen, als auch über die Registerkarte Komponenten in der Toolbox auf das Form ziehen. Im letzteren Fall erzeugt Visual Studio dann auch schon eine entsprechende Methode

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

}

Im nachfolgenden soll ein kleines Beispielprogramm die Verwendung der BackgroundWorker Klasse verdeutlichen. Dabei handelt es sich um ein sehr einfach gehaltenes Beispiel, bei dem der Text von zwei Labeln und der Zustand einer ProgressBar geändert werden soll. Über einen Schalter, soll der Vorgang gestartet werden. Zudem soll nach dem Start die Möglichkeit bestehen, den Vorgang vorzeitig abzubrechen.

Damit der BackgroundWorker diese Methode später auch aufruft, muss diese dem DoWork Ereignishandler hinzugefügt werden. Dies erfolgt im Beispielprogramm im Anschluss an die Methode InitializeComponent() durch Aufruf der Methode InitializeBackgroundWorker() im Konstruktor des Form.

private void InitializeBackgroundWorker()
{
     
backgroundWorkerExample.DoWork +=
        
new DoWorkEventHandler(backgroundWorkerExample_DoWork);
}

Innerhalb der DoWork Methode wird dann die zeitintensive Methode gestartet.

Wurde der Vorgang noch nicht gestartet, macht der Schalter Abbruch noch keinen Sinn. Deshalb wird das Propertie Enabled für den Abbruch Schalter auf false gesetzt. Ähnlich verhält es sich bei dem Schalter zum Starten des Vorgangs – nachdem der Vorgang gestartet wurde, wird der Start Schalter deaktiviert und im Gegenzug der Abbruch Schalter aktiviert.

Der BackgroundWorker wird also gestartet, wenn der Benutzer auf den Start Schalter klickt

private void btnStart_Click(object sender, EventArgs e)
{
      // Initialisierungen
     

     
// Starten des BackgroundWorker
     
backgroundWorker.RunWorkerAsync();
}

 

clip_image002

 

Es folgt nun der Programmcode – allerdings ohne den Designer-Code zum Erstellen des Formulars, da sich dieses wie oben abgebildet einfach erstellen lässt. Wichtig ist nur, daß die Namen der Elemente entsprechend dem nachfolgenden Code verwendet werden, damit das Programm ohne Änderungen funktioniert.

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace ExampleBackgroundWorker

{

   public partial class Form1 : Form

   {

      int loopCount;

      long y;

      public Form1()

      {

         InitializeComponent();

         InitializeBackgroundWorker();

      }

      private void InitializeBackgroundWorker()

      {

         backgroundWorkerExample.DoWork +=new DoWorkEventHandler
            (backgroundWorkerExample_DoWork);

         backgroundWorkerExample.ProgressChanged += new ProgressChangedEventHandler
            (backgroundWorkerExample_ProgressChanged);

         backgroundWorkerExample.RunWorkerCompleted +=
               new RunWorkerCompletedEventHandler(
                       backgroundWorkerExample_RunWorkerCompleted);

         backgroundWorkerExample.WorkerReportsProgress = true;

         backgroundWorkerExample.WorkerSupportsCancellation = true;

      }

      void backgroundWorkerExample_RunWorkerCompleted(object sender, 
                       RunWorkerCompletedEventArgs e)

      {

          if (e.Error != null)

         {

            MessageBox.Show(e.Error.Message);

         }

         btnCancel.Enabled = false;

         btnStart.Enabled = true;

      }

      void backgroundWorkerExample_ProgressChanged(object sender,
                              ProgressChangedEventArgs e)

      {

         lblInfo.Text = e.ProgressPercentage.ToString() + “ %“;

         pbPercent.Value = e.ProgressPercentage;

         lblResult.Text = y.ToString();

      }

   private void backgroundWorkerExample_DoWork(object sender, DoWorkEventArgs e)

   {

      BackgroundWorker worker = sender as BackgroundWorker;

      consumingMethod(worker, e);

   }

   void consumingMethod(BackgroundWorker worker, DoWorkEventArgs e)

   {

   while (loopCount <= 100)

   {

      for (int x = 0; x < 100000000; x++)

      {

         // Nur, damit was zu tun ist 😉

         y += x * loopCount;

      }

      if (worker.CancellationPending == true)

         return;

      worker.ReportProgress(loopCount++);

     }

   }

   private void btnStart_Click(object sender, EventArgs e)

   {

      loopCount = 0;

      y = 0;

      lblInfo.Text = string.Empty;

      btnStart.Enabled = false; // Start-Schalter wird deaktiviert

      btnCancel.Enabled = true; // Abbruch-Schalter wird aktiviert

      // Starten des BackgroundWorker

      backgroundWorkerExample.RunWorkerAsync();
      // –>  backgroundWorkerExample_DoWork(…);

   }

   private void btnCancel_Click(object sender, EventArgs e)

   {

      backgroundWorkerExample.CancelAsync();

      btnCancel.Enabled = false;

      btnStart.Enabled = true;

   }

  }

}