Visual C# 2012 Grundkurs

Events

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Events ermöglichen es einer Klasse oder einem Objekt, andere Klassen zu informieren, sollte sich der Status eines bestimmten Objekts verändern. Dieser Vorgang wird als Observer-Pattern bezeichnet.

Transkript

Im folgenden Abschnitt werden wir uns mit Events beschäftigen. Events und Delegates sind sich sehr ähnlich. Und ich werde erstmal mit Delegates beginnen, ein bestimmtes Szenario mit Delegates verwirklichen. Dann werde ich auf die Änderungen zu sprechen kommen, die sich auf die Verwendung von Events ergeben. Anwenden tut man Events ganz häufig in Situationen, wo man ein Paar von Objekten hat. Wo ein Objekt, das ist zentral, das repräsentiert einen bestimmten Status, und ein anderes Objekt, das möchte darüber informiert werden, wenn sich dieser Status ändert. Und das kann dann nicht nur ein anderes Objekt sein, das können X andere sein, von verschiedensten Typen. Ich habe ein Observable, und bei dem können sich jetzt Observer anmelden für eine Benachrichtigung, wenn sich bei diesem Observable etwas getan hat. Und das Ganze nennt  man das "Observer Pattern". Jetzt möchte ich ein bisschen Code schreiben, das dieses Observer Pattern in der Praxis einfach mal umsetzt. Ich habe jetzt eine Klasse "Manager" und eine Klasse "Mitarbeiter". Beide dieser Klassen haben eine Methode "do work". Nun ist es so, wenn der Manager etwas zu tun bekommt, dann macht er einfach Folgendes: Er delegiert die Aufgabe an den Mitarbeiter. Fertig. Dann kann man natürlich auch irgendwie noch ein bisschen Statusausgaben auf der Console machen, damit wir sehen, in welcher Reihenfolge was passiert. Jetzt tut der Mitarbeiter seine Arbeit. Irgendwie so. Jetzt ist es so, ich möchte, dass ein bisschen Zeit vergeht, während der Mitarbeiter diese Arbeit tut. Das kann man sehr schön mit der Klasse "Thread" machen, die hat nämlich eine Methode "Sleep", und da kann ich eine Anzahl von Millisekunden angeben, die der gegenwärtige Thread einfach mal angehalten werden soll. Ich gebe jetzt mal zwei Sekunden an, dann können wir nachher auf der Console sehr schön sehen, wann diese Pause entsteht. In Wirklichkeit schläft aber der Mitarbeiter nicht, sondern das ist  nur so ein Symbol dafür, dass er in dieser Zeit, in diesen 2000 Millisekunden, seine Arbeit tut. Wenn er fertig ist , dann wollen wir auf der Console das auch sehen. Dann ist der Mitarbeiter fertig. Ok. Und wie reagiert ein Manager, wenn der Mitarbeiter fertig ist? Vielleicht mal so. Das ist unsere Applikation. Und jetzt können wir das ganze Gebilde anstoßen. Ich lege so einen Manager an und sage ihm, er soll seine Arbeit tun. Jetzt starten wir die ganze Sache und schauen mal, was passiert. Die ersten zwei Zeilen sind da, danach kommt diese Pause, da tut der Mitarbeiter etwas, und dann kommt der Rest. Ich zeig es gerade noch einmal: die ersten zwei Zeilen und jetzt kommt der Rest. Das ist eigentlich nicht ganz das, was wir wollen, weil während der Mitarbeiter ächzend seine Arbeit tut, ist der Manager hier blockiert genau in dieser Zeit. Das heißt, in der Zeit kann der Manager nichts anderes tun. Aber, der Manager möchte ja vielleicht in der Zeit irgendwas sinnvolles tun, zum Beispiel Golf spielen gehen oder so etwas. Dafür muss ich das Programm jetzt ein bisschen umstellen. Das tue ich in der Weise indem ich eine sogenannte "Task" einsetze. Ich lege jetzt einfach diese Task einmal an. Diese Task will eine Action haben. Eine Action ist letztendlich eine Delegate, eine Delegate auf eine Methode, die keinen Parameter annimmt und keinen Return-Wert zurückgibt. Und genau so eine Methode haben wir ja da bei dem Mitarbeiter, also brauche ich im Grunde genommen einfach nur "Mitarbeiter.do work" hier schreiben, und damit ist diese Task hier angelegt. Jetzt kann ich die Task starten. Was jetzt das Wunderbare ist: Diese Task,  die wird jetzt nebenbei ausgeführt. Das spiegelt auch vielmehr die Situation wider. Der Mitarbeiter, während er etwas tut, kann ja der Manager was anderes tun. Und genau das können wir jetzt hier machen. Moment. Nur ist es jetzt so – das ist ein bisschen der Nachteil an der Geschichte der Manager kann jetzt im Augenblick noch nicht darauf reagieren, wenn der Mitarbeiter mit seiner Arbeit fertig ist. Ja nun möchte ich gerade einmal den gegenwärtigen Stand der ganzen Geschichte ablaufen lassen. Ich muss jetzt vielleicht noch eine Zeile hier einfügen, damit uns das Programm nicht davonläuft, während der Mitarbeiter noch am Arbeiten ist. Jetzt starte ich das Ganze mal und jetzt schauen wir mal, was wir hier haben. Sie sehen, der Manager sagt: "Mach mal hinne!" Und dann sagt er schon: "Ich bin dann mal Golf spielen." Und danach erst kommt der Mitarbeiter mit seiner Arbeit. Jetzt wenn er fertig ist, müsste der Manager eigentlich eine Chance haben, darauf zu reagieren, wenn der Mitarbeiter meldet, dass er eben seine Arbeit getan hat. Für diesen Zweck lege ich jetzt mal einen Delegate-Typ an, "Delegate-void Work done". Damit sage ich: "Work done" ist ein Delegate auf eine Methode, die keinen Wert zurück gibt und die keinen Parameter annimmt. Also eigentlich ähnlich wie eine Action. Im Grunde genommen könnte ich mir also diese Deklaration sparen und stattdessen eine Action verwenden. Aber, weil das Ganze geht ja in Richtung Events, ich möchte also jetzt trotzdem mal so ein Delegate definieren. Schön! Und jetzt kann der Mitarbeiter ein öffentliches Element zur Verfügung stellen hier. Das ist von diesem Work-Done-Typ, den ich hier oben deklariert habe, und das Ganze können wir jetzt mal "Work-- ach so, das muss ich groß schreiben, weil es öffentlich ist, "Work-Done-Handler" nennen. Wenn jetzt dieser Work-Done-Handler einen Wert enthält, dann kann er diesen Work-Done-Handler aufrufen. Ich kann jetzt diesen Delegate genau so aufrufen wie eine Methode von der gleichen Signatur. Nur das in dem Augenblick noch gar nicht klar ist, was die Implementierung der Methode sein wird. Jetzt kann der Manager eine Methode definieren, gehen wir mal hier hoch, also hier hat er das Mitarbeiterobjekt und jetzt kann er im "Work-Done-Handler" des Mitarbeiters eben mit einer Methode setzen, die entsprechend diese Meldung ausgibt, eben mit "das wurde aber auch Zeit" oder was auch immer. Hier können wir jetzt einen Lambda-Expression" zuweisen, die sieht dann etwas so aus, dass eine leere Parameterliste transferiert wird in diesen Code. Damit ist sichergestellt, dass  der Manager reagieren kann, wann immer der Mitarbeiter mit seiner Arbeit fertig ist. Starten wir mal den Code und schauen mal zu, ob das Ganze funktioniert. Und siehe da, es funktioniert. Der Manager sagt: "Mach mal hinne" und jetzt geht er erst mal Golf spielen. Der Mitarbeiter, der tut ächzend seine Arbeit, und wenn er fertig ist, dann sagt der Manager: "Das wurde aber auch Zeit." Das ganze System ist aber noch wesentlich flexibler. Ich könnte jetzt hier z.B. eine andere Klasse noch dazuschreiben, sagen wir mal "Class-Mama". Die "Class-Mama" könnte jetzt z.B. einen "Property-Sohn" haben. Ich habe hier eine Variable und um diese Variable wickle ich jetzt mal einen "Property" herum, aber im Grunde genommen braucht das Property nur einen Setter, das muss jetzt von außen nur gesetzt werden. Jetzt könnte ich sagen-- ich könnte diesen Workhandler hier um eine weitere Methode ergänzen. Da muss ich jetzt gerade mal auch so einen Plus-gleich verwenden. Ich habe jetzt hier, bei dem Manager, einen Handler gesetzt. Jetzt will ich aber mehrere Handler haben. Es sollen verschiedene Leute darauf reagieren können, dass der Mitarbeiter fertig ist. Und deswegen nehme ich hier das Plus-gleich. Ich addiere einen Handler und genau das tut auch die Mama. Die addiert hier einen Handler, und der sieht jetzt so ähnlich aus wie der von dem Manager, nur das ein anderer Text entsteht. So etwas würde vielleicht die Mama sagen. Jetzt muss ich nur noch dafür sorgen, dass die Mama in irgendeiner Weise in diese Kette der Ereignisse eingebunden wird. Das könnte ich z.B. jetzt machen, wenn der Mitarbeiter angelegt wird. Dann kann der Mitarbeiter seine Mama anlegen und könnte dann sich selbst bei der Mama als Sohn eintragen. Gut. Damit ist klar, sobald der Sohn sich bei der Mama einträgt, wird auf der anderen Seite dieser Handler gesetzt, und dann kann die Mama sozusagen drauf reagieren, wenn der Sohn fertig ist. Jetzt wollen wir mal schauen, ob das alles funktioniert. Wunderbar. Der Mitarbeiter tut hier seine Arbeit und wenn er fertig ist, bekommt er unterschiedliche Reaktionen von unterschiedlichen anderen Objekten. Die ganze Geschichte hat jetzt zwei Nachteile. Nachteil Nummer eins ist, dass dieser Work-Done Handler eine öffentliche Variable ist, und jeder kann diese Variable überschreiben. Hier in dem Konstruktor von Mitarbeitern passierte die ganze Geschichte mit der Mama. Was der Manager jetzt tun könnte, der könnte also ganz grausam diesen Work-Done-Handler einfach mit seinem eigenen Handler überschreiben, und damit hätte die Mama gar keine Chance mehr zu reagieren. Ich zeige das gerade mal, ich führe den Code aus, und man sieht, die Reaktion der Mama fehlt jetzt, weil sie schlichtweg von dieser Managerreaktion überschrieben worden ist. Das ist natürlich jetzt nicht exakt das Verhalten, wie wir es haben wollen. Aber es kommt noch besser, also ich ändere den Code jetzt wieder so ab, dass er wie ursprünglich ist. Was auch ziemlich blöde ist, ist dass jeder von außen diesen Handler aufrufen kann. Das ergibt ja jetzt überhaupt gar keinen Sinn. Ich führe jetzt diesen Code mal aus, also, man sieht, durch dieses Plus-gleich kommt jetzt die Mama sozusagen wieder zurück ins Geschäft. Jetzt ruft der Manager diesen "Work-Done-Handler" auf, bevor er den Mitarbeiter überhaupt beauftragt hat. Man sieht jetzt mal, was da passiert, nämlich, dass diese ganzen Reaktionen, dass die jetzt hier gleich am Anfang erscheinen, also bevor der Mitarbeiter überhaupt eine Chance hat, seine Arbeit zu tun. Und auch das ist eigentlich nicht ganz der Sinn der Sache. Delegates sind für diese Art an Aufgabe nicht ganz geeignet. Für diese Art von Aufgaben, dafür gibt es die Events, und es braucht eigentlich gar nicht viel, diesen Code so umzuschreiben, um aus diesen Delegates ein Event zu machen und zwar brauche ich im Grunde genommen einfach nur hier das Schlüsselwort "Event" davorschreiben. Damit sage ich, als Mitarbeiter publiziere ich hier ein "Event" vom Delegatetyp WORK DONE und dieses "Event", damit es schöner ist, möchte ich das jetzt umbenennen. Es gibt übrigens so ein wunderschönes Rename-Tool. Man drückt einfach auf die F2 Taste, F2 unter Windows ist ja immer das "Umbenennen". Man stellt also den Cursor auf diesen Namen WORK DONE HANDLER, drückt die F2 Taste und jetzt kann ich schreiben WORK DONE EVENT, bestätige das Ganze und siehe da, das "Event" ist an allen Stellen des Cods umbenannt. So werden "Events" normalerweise benannt. Man hat so einen Delegate von einem bestimmten Typ, und das ist auch genau der Punkt, warum ich jetzt hier keine Action verwendet habe, weil das immer so zusammenpassende Paare sind. Dieser Delegatetyp und der Eventname, der sich eben dann aus diesem Delegate-Typ und diesem Wort-event zusammensetzt. Schön, jetzt ist also aus diesem Delegate, aus diesem öffentlichen Delegate, ein Event geworden. Und man sieht schon mal, dass das was ich jetzt hier gemacht habe, dieser Blödsinn, nämlich diesen Delegate von außen aufzurufen, genau das ist jetzt nicht mehr erlaubt. Also muss ich diesen Code schon mal entfernen. Und die andere Geschichte die nachteilig war, nämlich dass ich einen Event einfach überschreiben kann, also so einen Delegate einfach überschreiben kann, auch das funktioniert nicht. Ich kann nur entweder Handler hinzufügen oder Handler wegnehmen. Ich könnte hier jetzt diesen Handler auch wegnehmen, das will ich aber nicht, sondern ich füge ihn hier einfach nur mal hinzu. Ok, jetzt bin ich ja noch den Beweis schuldig geblieben, dass dieser Code nach diesem Hinzufügen dieses Event-Schlüsselworts genauso funktioniert wie vorher. Ich starte die ganze Sache jetzt einmal und der Code funktioniert genauso wie vorher. Das heißt, sowohl die Mama als auch der Manager werden über das Fertigwerden der Arbeit informiert. Das war es jetzt mit diesem Abschnitt zu den Events. Die Events sind dafür da, um eben dieses "Observable Pattern" zu implementieren. Wir haben eine Observable und bei dieser Observable können sich verschiedene Observer anmelden und können im Falle von bestimmten Ereignissen benachrichtigt werden.

Visual C# 2012 Grundkurs

Schreiben Sie eigene Programme in C# und lernen Sie dazu alle Schlüsselwörter und die meisten Konstrukte kennen, um sicher mit dieser Programmierspreche umzugehen.

7 Std. 1 min (44 Videos)
Derzeit sind keine Feedbacks vorhanden...

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!