Threads

Aus Wiki des Deutschsprachige Xbaseentwickler e. V.
Version vom 25. Mai 2013, 11:54 Uhr von Georg (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „ == Threads == Am weitesten entfernt von Clipper ist das Konzept der Threads. Während unter DOS quasi alle Programme (auch die speicherresidenten) sich einen…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Threads

Am weitesten entfernt von Clipper ist das Konzept der Threads. Während unter DOS quasi alle Programme (auch die speicherresidenten) sich einen einzigen Thread teilen mussten, ist es unter Windows so, dass ein Programm quasi in mehreren Threads (wörtlich "Fäden") laufen kann. Was Multitasking auf Betriebssysteme ist, das ist Threading innerhalb eines Programms.

Im normalen, prozeduralen Ablauf erfolgt auf die Anforderung, eine Liste zu drucken, der Druck der Liste. Solange die Liste gedruckt wird, ist das Programm ausschliesslich mit der Liste beschäftigt, und alle anderen Anforderungen (Events) landen erst einmal in einer Warteschlange.

Mittels Threads lassen sich solche Aufgaben (Tasks) programmintern "auslagern" und werden dann quasi im Hintergrund abgewickelt.


Besonderheiten von Threads

Threads lassen sich von aussen kaum beeinflussen. Dazu gehört auch, dass mit Xbase++ Standard-Werkzeugen ein Thread nicht von aussen beendet werden kann. Mehr dazu in den Anwendungsbeispielen.

Jeder Thread hat seinen eigenen WorkSpace, d.h. Dateien, auf die zugegriffen werden soll, müssen in einem Thread (erneut) explizit geöffnet werden.

Bestimmte Einstellungen wie SOFTSEEK etc. sind immer nur thread-local.

Als STATIC deklarierte Variablen sind nicht thread-local, d.h. wenn ein Thread eine STATIC Variable verändert, greifen alle anderen Threads auf die eine, veränderte Variable zu.


Das Erzeugen eines Threads

Für das Erzeugen eines Threads wird die Funktion Thread() verwendet. Diese Funktion liefert ein Objekt der Thread-Klasse zurück.

  oThread := Thread():new()
  oThread:start("GenerateDialogThread")
oder
  oThread:start({|| GenerateDialogThread()})

Die Funktion Thread() liefert mit der Methode :new() ein Objekt der Thread-Klasse zurück. Dieses Objekt selbst ist noch im Ruhe-Zustand. Erst durch die Methode :start() wird der Thread aktiviert, indem die Funktion GenerateDialogThread aufgerufen wird. Analog zu Eval können in der Methode :start() Parameter an die aufzurufende Funktion übergeben werden.

Die Methode :start() erwartet entweder einen String (d.h. in diesem Fall darf die aufzurufende Funktion nicht als STATIC deklariert sein) oder einen Codeblock.


Anwendungsbeispiele

Anzeige der Uhrzeit

Das klassische Beispiel wäre die Darstellung einer Uhrzeitanzeige im Programm (das übernimmt inzwischen die Taskleiste). Vom Prinzip verdeutlicht diese Anwendung aber sehr gut, worum es bei Threads geht: es läuft eine Programmverarbeitung, die von anderen Programmteilen innerhalb des Programms logisch getrennt ist.


Browse und Edit in verschiedenen Threads

Die Standard-Programmierung von Browse und Edit stellt eine klassische Windows-Falle dar. Während "früher" das Browse-Fenster im Hintergrund blieb und erst nach Ende des Edit wieder aktiv wurde, kann der Benutzer heute zwischen den Fenstern wechseln (und erwartet diese Möglichkeit auch) und gegebenenfalls im Browse den Record-Pointer verschieben. Wenn nach Abschluss des Edit der Datensatz aktualisiert wird, geht die Änderung dann schon mal auf den falschen Satz, wenn man als Programmierer diesen Fall nicht berücksichtigt hat.

Laufen Browse und Edit in unterschiedlichen Threads, so hat jeder Thread einen eigenen Zugriff auf die Datei, und wenn im Browse-Fenster der Record-Pointer verschoben wird, ändert sich im Edit-Thread nichts.

Dies stellt einen Gewinn dar, eröffnet aber ein anderes Problem: wenn der Anwender im Edit-Thread Daten verändert hat, wie erklärt man dem Browse, dass aktuelle Daten anzuzeigen sind?

(es folgt noch mehr Text)