Eine Einführung in das Threading in VB.NET

Um das Threading in VB.NET zu verstehen, ist es hilfreich, einige der Grundkonzepte zu verstehen. Zunächst einmal geschieht das Threading, weil es vom Betriebssystem unterstützt wird. Microsoft Windows ist ein vorbeugendes Multitasking-Betriebssystem. Ein Teil von Windows, der so genannte Task Scheduler, verteilt die Prozessorzeit auf alle ausgeführten Programme. Diese kleinen Teile der Prozessorzeit werden als Zeitscheiben bezeichnet. Programme sind nicht dafür verantwortlich, wie viel Prozessorzeit sie erhalten, sondern der Taskplaner. Weil diese Zeitscheiben so klein sind, entsteht die Illusion, dass der Computer mehrere Dinge gleichzeitig erledigt.

Definition von Thread

Ein Thread ist ein einzelner sequentieller Steuerungsfluss.

Einige Qualifikanten:

  • Ein Thread ist ein "Ausführungspfad" durch diesen Code.
  • Threads teilen sich den Speicher, sodass sie zusammenarbeiten müssen, um das richtige Ergebnis zu erzielen.
  • Ein Thread verfügt über threadspezifische Daten wie Register, einen Stapelzeiger und einen Programmzähler.
  • Ein Prozess ist ein einzelner Code, der viele Threads haben kann, aber mindestens einen und einen einzelnen Kontext (Adressraum) hat..

Dies ist etwas auf Baugruppenebene, aber genau darauf kommen Sie, wenn Sie anfangen, über Threads nachzudenken.

Multithreading vs. Multiprocessing

Multithreading ist nicht dasselbe wie Multicore-Parallelverarbeitung, aber Multithreading und Multiprocessing funktionieren zusammen. Die meisten PCs haben heutzutage Prozessoren mit mindestens zwei Kernen, und normale Heimcomputer haben manchmal bis zu acht Kerne. Jeder Kern ist ein separater Prozessor, der Programme für sich ausführen kann. Sie erhalten eine Leistungssteigerung, wenn das Betriebssystem verschiedenen Kernen einen anderen Prozess zuweist. Die Verwendung mehrerer Threads und Prozessoren für eine noch höhere Leistung wird als Parallelität auf Thread-Ebene bezeichnet.

Vieles, was getan werden kann, hängt davon ab, was das Betriebssystem und die Prozessorhardware können, nicht immer, was Sie in Ihrem Programm tun können, und Sie sollten nicht erwarten, dass Sie mehrere Threads für alles verwenden können. Tatsächlich finden Sie möglicherweise nicht viele Probleme, die von mehreren Threads profitieren. Implementieren Sie also kein Multithreading, nur weil es vorhanden ist. Sie können die Leistung Ihres Programms leicht reduzieren, wenn es kein guter Kandidat für Multithreading ist. Video-Codecs können beispielsweise die schlechtesten Programme für Multithreading sein, da die Daten von Natur aus seriell sind. Serverprogramme, die Webseiten verarbeiten, gehören möglicherweise zu den besten, da die verschiedenen Clients von Natur aus unabhängig sind.

Thread-Sicherheit üben

Multithread-Code erfordert häufig eine komplexe Koordination von Threads. Subtile und schwer zu findende Fehler treten häufig auf, da unterschiedliche Threads häufig dieselben Daten gemeinsam nutzen müssen, damit Daten von einem Thread geändert werden können, wenn ein anderer dies nicht erwartet. Der allgemeine Begriff für dieses Problem ist "Race Condition". Mit anderen Worten, die beiden Threads können sich zu einem "Rennen" zusammenschließen, um dieselben Daten zu aktualisieren, und das Ergebnis kann je nachdem, welcher Thread "gewinnt", unterschiedlich ausfallen. Nehmen wir als einfaches Beispiel an, Sie codieren eine Schleife:

Wenn der Schleifenzähler "I" unerwartet die Zahl 7 überspringt und von 6 auf 8 wechselt - aber nur zu einem gewissen Zeitpunkt -, hätte dies katastrophale Auswirkungen auf das, was die Schleife gerade tut. Das Verhindern derartiger Probleme wird als Threadsicherheit bezeichnet. Wenn das Programm das Ergebnis einer Operation in einer späteren Operation benötigt, kann es unmöglich sein, parallele Prozesse oder Threads zu codieren, um dies zu tun. 

Grundlegende Multithreading-Operationen

Es ist Zeit, diese Vorsichtsmaßnahme in den Hintergrund zu rücken und Multithreading-Code zu schreiben. Dieser Artikel verwendet zur Vereinfachung eine Konsolenanwendung. Wenn Sie mitmachen möchten, starten Sie Visual Studio mit einem neuen Konsolenanwendungsprojekt.

Der von Multithreading verwendete primäre Namespace ist der System.Threading-Namespace, und die Thread-Klasse erstellt, startet und stoppt neue Threads. Beachten Sie im folgenden Beispiel, dass TestMultiThreading ein Delegat ist. Das heißt, Sie müssen den Namen einer Methode verwenden, die die Thread-Methode aufrufen kann.

In dieser App hätten wir das zweite Sub ausführen können, indem wir es einfach aufrufen:

Dies hätte die gesamte Anwendung seriell ausgeführt. Das erste obige Codebeispiel startet jedoch die Unterroutine TestMultiThreading und fährt dann fort.

Ein Beispiel für einen rekursiven Algorithmus

Hier ist eine Multithread-Anwendung, bei der Permutationen eines Arrays mithilfe eines rekursiven Algorithmus berechnet werden. Hier wird nicht der gesamte Code angezeigt. Das zu permutierende Array von Zeichen ist einfach "1", "2", "3", "4" und "5". Hier ist der relevante Teil des Codes.