Threads für Einsteiger

Vom präemptiven Multithreading bis zur echten Parallelisierung

Programme laufen schneller, wenn man sie auf mehrere Prozessorkerne verteilt. Deswegen kommt dem Multithreading in der Entwicklung immer größere Bedeutung zu. Wenngleich es einige Fallstricke mit sich bringt, müssen Sie auch als weniger versierter Hobbyprogrammierer nicht außen vor bleiben.

Vom präemptiven Multithreading bis zur echten Parallelisierung

© Hersteller/Archiv

Vom präemptiven Multithreading bis zur echten Parallelisierung

Das Betriebssystem verwaltet die auf ihm ausgeführten Programme als Prozesse mit einem oder mehreren Threads. Die Prozesse sind eigentlich reine Verwaltungseinheiten. Sie besitzen einen eigenen Adressraum sowie diverse Betriebssystemressourcen wie Codesegment, Datensegment etc.

Für die Ausführung des Programmcodes sind allein die Threads zuständig. Jeder Prozess besitzt daher zumindest einen Thread, der automatisch bei der Prozessinitialisierung erzeugt wird. Man spricht in diesem Zusammenhang vom Initial- oder Hauptthread. Auf einem Computer mit mehreren Prozessoren (Multicore) verteilt Windows die auszuführenden Threads gleichmäßig auf die Prozessoren.

Es gibt allerdings für das Betriebssystem keine Möglichkeit, die Ausführung eines Threads auf mehrere Prozessoren aufzubrechen. Für ein Programm, das nur aus einem einzigen Thread besteht, bedeutet dies, dass die Ausführung auf einem Multicore-Computer kaum zu einer Laufzeitverbesserung führen wird.

Folglich müssen Sie als Programmierer den Code auf mehrere Threads verteilen, damit Ihr Programm von einer Multicore-Architektur profitieren kann.

Es gibt aber noch einen anderen Grund, das zu tun, nämlich um zu vermeiden, dass die Benutzeroberfläche Ihres Programms einfriert. Sehen Sie sich dazu das C++-Listing in der Datei Beispiellisting.txt der Heft-DVD an (es stammt aus dem Beispielprojekt iniSearch1 ebenfalls von der DVD).

INI-Dateien suchen, software, programmierung

© Hersteller/Archiv

Der Befehl INI-Dateien suchen ist deaktiviert, solange die Suche läuft.

Das Programm soll dem Benutzer beim Aufspüren von .ini-Dateien helfen. Die GUI besteht aus einem einfachen Menü und einer ListBox. Wenn der Anwender den Menübefehl Datei/INI-Dateien suchen aufruft, durchsucht das Programm das Laufwerk C:\ nach .ini-Dateien und trägt alle gefundenen Dateien in das Listenfeld ein.

Die Ereignisbehandlungsmethode zu dem Menübefehl INI-Dateien suchen (iniDateienSuchenToolStripMenuItem_Click()) leert zunächst das Listenfeld für den Fall, dass der Befehl wiederholt aufgerufen wird, und ruft dann die rekursive Methode sucheINIs() auf. Mit dem ersten Parameter legen Sie das zu durchsuchende Laufwerk - hier C:\ - fest.

Im zweiten Parameter inidateien speichert die Methode sucheINIs() die gefundenen .ini-Dateien als FileInfo-Objekte. Über diesen Parameter stellen Sie in der Methode iniDateienSuchenToolStripMenuItem_Click() nach Abschluss der Suche eine Datenbindung zwischen dem Listenfeld und der FileInfo-Auflistung her (listBox1->DataSource = inidateien; - mit listBox1->DisplayMember = "FullName"; legen Sie fest, dass im Listenfeld die Dateinamen samt Pfad erscheinen).

Soweit so gut, das Problem dieser Implementierung ist, dass je nach Größe des Laufwerks C:\, der Anzahl der Unterverzeichnisse und der Anzahl der gefundenen Dateien es selbst auf aktuellen und schnellen Computern unter Umständen einige Zeit dauern wird, bis der oberste Aufruf der Methode sucheINIs() (in der Ereignisbehandlungsmethode für den Menübefehl INI-Dateien suchen) zurückkehrt.

Bevor die Rekursion aber nicht beendet ist, kann der Anwender mit dem Programm nicht weiterarbeiten. Es bleibt nichts anderes übrig als abzuwarten, bis die Suche beendet ist.

Am schnellsten stellen Sie die Reaktionsfähigkeit von lahmgelegten Benutzeroberflächen dadurch wieder her, dass Sie innerhalb der Codeblöcke, die für die Lahmlegung verantwortlich sind, wiederholt die Methode DoEvents() der Application-Klasse aufrufen.

Im vorliegenden Beispiel ist dies nicht weiter schwierig, da die verantwortliche Methode sucheINIs() sich in einer Schleife selbst rekursiv aufruft und der hohe Zeitbedarf vor allem durch die Vielzahl der rekursiven Aufrufe (gleich Schleifendurchläufe) entsteht. Sie brauchen also nur den Aufruf von Application::DoEvents() in die Schleife einzubauen:

void sucheINIs(DirectoryInfo^ verzeich
nis, List<FileInfo^>^ inidateien)
{ ... for each (DirectoryInfo^ verz in verzeichnisse)
{ Application::DoEvents();
try
{ sucheINIs(verz, inidateien); }
catch (UnauthorizedAccessException^
e) {} } ... }

Die Benutzeroberfläche bleibt nun auch nach Aufruf des Befehls INI-Dateien suchen reaktionsfähig. Wenn Sie verhindern möchten, dass der Anwender diesen Befehl erneut verwendet, während die Suche noch läuft, deaktivieren Sie diese Option vorübergehend, indem Sie vor Aufruf der Methode sucheINIs() die Eigenschaft enabled des ToolStripMenuItem auf false und anschließend wieder auf true setzen. 

Mehr zum Thema

HTML 5
Webgestaltung

Google Web Designer ist spezialisiert auf HTML5. Ein Vorteil dieses Standards ist das einfache Einbinden von Videos mit dem Element video. Wir zeigen…
Wir verraten, wie Sie Fritzboxen und andere Router vor Hackern schützen.
Fritzbox, Asus, Belkin und Co.

Fritzbox, Asus, Belkin oder DLink - die Liste der geknackten Router ist lang. Hacker stahlen Passwörter oder NAS-Daten. So machen Sie Ihren Router…
Wir führen Sie zur eigenen Windows-App - unserem PC-Magazin-RSS-Feed.
C# und XAML

Wir zeigen, wie Sie Windows 8.1 Apps selbst programmieren können. Lernen Sie das App erstellen an Hand unseres Beispiels: dem RSS-Feed von PC…
Windows Tipps & Tricks: Benutzerrechte unter Windows 8.1
Programme richtig installieren

Wir zeigen Ihnen, wie Sie sich unter Windows 8.1 alle Benutzerrechte verschaffen und Programme richtig installieren.
Windows 8: Starbildschirm
Microsoft Project Siena

Erstellen Sie sich selbst eine App für Windows 8, die auf alle Funktionen Ihres Tablets zugreifen kann, inklusive Kamera, Mikrofon und Lautsprecher.…