Site logo
Site logo
Programmieren aus Leidenschaft
Programmieren aus Leidenschaft

Threads mit Events


Der große Vorteil von Multithreading-Anwenungen ist natürlich, dass zeitaufwendige Arbeitsabläufe asynchron zum Hauptprogramm ablaufen und dadurch das Programm weiterhin bedienbar bleibt, ohne dass die Benutzeroberfläche blockiert. Diese Art der parallelen Verarbeitung hat allerdings einen Schönheitsfehler. Denn es ist für das Hauptprogramm schwer feststellbar, was ein Thread gerade tut oder ob die Verarbeitung eventuell sogar schon abgeschlossen ist.

Es wäre also sinnvoll, wenn ein Thread dem Hauptprogramm mitteilen würde, was er gerade tut oder wie der Zustand bestimmter Vorgänge ist. Dafür eignen sich in C# Events (deutsch: Ereignisse).

Für unser Beispiel entwerfen wir eine einfache Klasse mit einer Methode, die wir später in einem separaten Thread ausführen werden. Wir werden hier nur zwei Werte addieren, etwas das man eigentlich nicht in einem Thread ausführen müsste. Aber es ist ideal um das Beispiel einfach zu halten. Der Aufbau der Klasse beginnt ganz einfach mit drei Feldern, welche die benötigten Werte aufnehmen können.

public int wert1 = 0;
public int wert2 = 0;
public int ergebnis = 0;


Die nächsten Schritte sind ein Event und ein Delegate.

public delegate void berechnungFertig(int e);
public event berechnungFertig fertig;


Den Event nennen wir der Einfachheit halber „fertig“, denn er soll ausgeführt werden, wenn die Berechnung abgeschlossen ist. Dazu kommt ein Delegate, der Methoden mit dem Parameter „int“ aufnehmen kann. Das wird gleich unser Ergebnis. Die Methode, welche dann im Thread abläuft, sieht so aus:

public void ausrechnen()
{
   this.ergebnis = this.wert1 + this.wert2;
   fertig(ergebnis);
}


Zuerst werden beide Werte addiert. Anschließend wird der „fertig“-Event ausgelöst. Durch die Zuweisung des Delegaten „berechnungFertig“ zu dem „fertig“-Event werden auch die Felder bestimmt, die der Event übertragen kann. Hier nur ein Feld, definiert als „int“, also eine ganze Zahl. Unser Ergebnis.

Jetzt noch einmal die ganze Klasse im Zusammenhang:

class ThreadClass
{
   public int wert1 = 0;
   public int wert2 = 0;
   public int ergebnis = 0;

   public delegate void berechnungFertig(int e);
   public event berechnungFertig fertig;

   public void ausrechnen()
   {
      this.ergebnis = this.wert1 + this.wert2;
      fertig(ergebnis);
   }
}


Diese Berechnung jetzt wirklich im Thread ablaufen zu lassen ist die nächste Aufgabe. Dafür müssen wir uns von der soeben erzeugten Klasse ein Objekt erzeugen und die Werte mit den zu addierenden Zahlen füllen.

ThreadClass myTC = new ThreadClass();
myTC.wert1 = 122;
myTC.wert2 = 77;


Auch der „fertig“-Event ist Teil dieses Objektes. Die Aufgabe besteht jetzt nur noch darin, diesem Event eine Methode zuzuweisen, die beim Auftreten des Ereignisses ausgeführt wird.

myTC.fertig += new ThreadClass.berechnungFertig(myTC_fertig);

Visual Studio hat hier eine sehr praktische Eingabehilfe. Nachdem man „+=“ getippt hat, genügt es, zwei Mal die Tabulator-Taste zu drücken und der Rest der Definition, einschließlich einer passenden Methode, wird automatisch erstellt. Die Methode „myTC_fertig“ hat auch wieder einen „int“-Paramter. Dieser wird durch den Delegate bestimmt und durch den Event übertragen. Nachdem wir die Methode mit einer Messagebox ausgestattet haben, sollte sie so aussehen.

void myTC_fertig(int e)
{
   MessageBox.Show(e.ToString());
}


Damit ist fast die ganze Arbeit getan. Jetzt erzeugen wir nur noch einen neuen Thread, weisen ihm unsere „ausrechnen“-Methode zu und starten ihn.

Thread myThread = new Thread(myTC.ausrechnen);
myThread.Start();

Zum Schluss noch ein Mal diesen Teil des Programms komplett. Der Thread wird durch einen Klick auf Button1 ausgelöst.

private void button1_Click(object sender, EventArgs e)
{
   ThreadClass myTC = new ThreadClass();
   myTC.wert1 = 122;
   myTC.wert2 = 77;
   myTC.fertig += new ThreadClass.berechnungFertig(myTC_fertig);

   Thread myThread = new Thread(myTC.ausrechnen);
   myThread.Start();
}

void myTC_fertig(int e)
{
   MessageBox.Show(e.ToString());
}