Also bei Threads halte ich mich immer an folgende
Regeln:
1.) keine Windows-
API Funktionen (z.B. BeginThread()) verwenden, sondern immer nur von der TThread-Klasse ableiten.
Der direkte Aufruf von Windows-
API Funktionen ist hier viel zu gefährlich und fehlerträchtig.
Warum sich unnötigerweise in Gefahr begeben nur um einige Bytes und Microsekunden zu sparen?
2.) falls viele kleine Aufgaben zu erledigen sind, sollte man einen Threadpool in Betracht ziehen
3.) ein Thread sollte möglichst selbstständig und ohne Kontakt zu anderen Threads ablaufen.
Das bedeutet insbesondere: nicht auf globale Variablen zugreifen (ausser es geht nicht anderst).
Natürlich auch keine Funktionen aufrufen, die mit globalen Daten arbeiten.
Das Thread-Objekt bekommt alle nötigen Daten von Aussen über Properties übergeben und arbeitet dann mit seiner lokalen Kopie.
Die Ergebnisse des Threads werden über Properties zurückgegeben.
Man könnte die Thread-Klasse also unverändert ausschneiden und in ein anderes Programm einfügen, weil sämtliche Abhängigkeiten über Properties der Klasse bedient werden.
Das Prinzip ist EVA: Eingabe - Verarbeitung - Ausgabe
4.) Kommunikation mit der
VCL vermeiden bzw. so gering wie möglich halten
5.) Innerhalb der Execute-Methode sollte man immer wieder das Property Terminated abfragen (Falls True, Thread sofort beenden)
Fragt man Terminated zu häufig ab, bremst das den Thread, fragt man zu selten oder gar nicht ab, behindert das das Verhalten (z.B. beim Herunterfahren von Windows).
6.) Exceptions innerhalb des Threads abfangen (andernfalls gehen sie verloren)
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
try
InternalExecute;
ReturnValue := 0;
except
on E:
Exception do
begin
OutputDebugString(PChar(E.
Message));
ReturnValue := -1;
self.ExceptMessage := E.
Message;
// Meldung für später in einem Property merken
end;
end;
Besonders Punkt 3. ist in der Praxis nicht so einfach und kann auch je nach Aufgabe nicht immer so erfolgen.
Aber die Probleme werden merklich reduziert.