Threads für Einsteiger

Vom präemptiven Multithreading bis zur echten Parallelisierung

18.11.2011 von Walter Saumweber

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.

ca. 2:35 Min
Ratgeber
VG Wort Pixel
Vom präemptiven Multithreading bis zur echten Parallelisierung
Vom präemptiven Multithreading bis zur echten Parallelisierung
© Hersteller/Archiv

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
Der Befehl INI-Dateien suchen ist deaktiviert, solange die Suche läuft.
© Hersteller/Archiv

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. 

Nächste passende Artikel

Threads kommt vorerst nicht in die EU.

Social-Media

Threads: Twitter-Klon "verliert mehr als die…
Dem Twitter-Konkurrenten Threads drohen kurz nach dem Start erste Probleme.

Ärger um Kurznachrichtendienst

Threads: Enge Instagram-Verbindung, Twitter…
Threads kommt vorerst nicht in die EU.

Social-Media

Threads: Metas Twitter-Klon kommt nicht nach…
Überrasch’ mich!
mehrweniger

Mehr zum Thema

HTML 5

Webgestaltung

Google Web Designer: Videos einbinden mit HTML5

Wir verraten, wie Sie Fritzboxen und andere Router vor Hackern schützen.

Fritzbox, Asus, Belkin und Co.

WLAN-Router vor Hackern schützen - so geht's

Wir führen Sie zur eigenen Windows-App - unserem PC-Magazin-RSS-Feed.

C# und XAML

Windows 8.1 Apps programmieren - so geht's

Windows Tipps & Tricks: Benutzerrechte unter Windows 8.1

Programme richtig installieren

Benutzerrechte unter Windows 8.1

Windows 8: Starbildschirm

Microsoft Project Siena

Wie Sie Windows-8-Apps selber erstellen

Weiter zur Startseite