Möglicherweise ist die Funktionsweise von Actions oder das Locking nicht jedem geläufig, also sollen hier die Änderungen erläutert werden.
- Einführung der Variable lockObject: Dies ist notwendig, weil sichergestellt werden soll, dass jeweils nur ein Thread den Wert der Iteration aktualisiert, um einen Datenüberlauf („Race Condition“) zu vermeiden. Race Conditions sind zwar selten, führen aber zu Datenkorruption.
- Deklaration für forLoop: Wo ursprünglich das Statement for verwendet wurde, wird nun ein Action
deklariert. Hier wurde die Lambda-Syntax verwendet, die dasselbe bewirkt. Der Inhalt der for-Schleife wurde hier als Hauptteil für die Action verwendet, und dieser Block wurde mit einem Strichpunkt abgeschlossen, was das Ende des Deklarations-Statements bildet. - Der lock-Block: Der Code, der den Iterationswert aktualisiert, wurde in den lock-Block eingeschlossen (SyncLock in VB.NET). lockObject ist der Schlüssel für das „Schloss“. Zwei lock-Blocks mit unterschiedlichen Schlüsseln können gleichzeitig ausgeführt werden, doch wenn mehrere Blocks mit demselben Schlüssel gleichzeitig ausgeführt werden sollen, geht das nicht. Sie werden nacheinander ausgeführt, um die mögliche Race Condition um das Statement iteration++ zu vermeiden. Eine gute Faustregel wäre, lock jedesmal zu verwenden, wenn eine Variable aktualisiert werden soll. Wenn mehr Kontrolle über die Freigabe der Sperre nötig ist, kann stattdessen Monitor.Enter() und Monitor.Exit() verwendet werden.
- Aufruf von Parallel.For(): Statt eines for-Statements werden die Startzahl, Endezahl und das Action<int> an Parallel.For() übergeben.
Wie man sieht, ist nur wenig Aufwand nötig, um die bestehende for-Schleife für die Verwendung von Parallel.For() zu verändern. Bei Verwendung von .NET 4 kann dies direkt erfolgen, und man sieht ohne viel Aufwand eine Performance-Steigerung bei bestehenden und neuen Anwendungen.
Parallel.ForEach ist sogar noch einfacher. Hier ist der Original-Code, der eine Liste von Zahlen in Reihenfolge erstellt und dann auf den Bildschirm ausgibt:
Und hier ist eine parallel operierende Version:
Das ist wirklich unkompliziert.
Parallel.Invoke() ist anfangs vielleicht etwas verwirrend, aber in der Praxis ebenso einfach. Parallel.For und Parallel.ForEach werden verwendet, wenn genau derselbe Code mehrmals mit unterschiedlichen Input-Parametern aufgerufen werden soll. Parallel.Invoke ist praktischer, wenn unterschiedliche Codeteile gleichzeitig aufgerufen werden sollen. Sollen beispielsweise Daten von einer Netzwerkadresse gelesen, ein Web-Service aufgerufen und etwas auf dem Bildschirm ausgegeben werden soll, ist dies eine gute Methode, alles gleichzeitig zu erledigen und Zeit zu sparen. Hierzu wird einfach ein Array von Action<>-Objekten erstellt und dieser Array an Parallel.Invoke() übergeben:
Damit werden Daten von der URL heruntergeladen und gleichzeitig auf dem Bildschirm ausgegeben. Dies ist ein eher triviales Beispiel, doch macht es deutlich, wie nützlich die Methode für das tägliche Programmieren sein kann. Wiederum wird hier mit wenig Aufwand durch Packen des Codes in Action-Objekte eine paralleles Operieren erreicht. Nicht schlecht für wenige Minuten Arbeit.
Neueste Kommentare
Noch keine Kommentare zu Verwendung der Parallel-Klasse für einfaches Multithreading
Kommentar hinzufügenVielen Dank für Ihren Kommentar.
Ihr Kommentar wurde gespeichert und wartet auf Moderation.