Achja, das wäre natürlich auch eine einfachere Variant die Werte zurückzugeben. Ich nehme an, du meinst es beispielhaft so?
Delphi-Quellcode:
type
// Definition des Events mit allen relevanten Parametern
TTestCompleteEvent = procedure(Sender: TObject; const ResultText: string; AllesOk: Boolean;
ScreenWidth, ScreenHeight: Integer;
ScreenDimensionMismatch, Vollbild: Boolean;
CurrentMonitor: Integer) of object;
TTestThread = class(TThread)
private
FOnTestComplete: TTestCompleteEvent;
FResultText: string;
FAllesOk: Boolean;
procedure DoNotifyTestComplete;
protected
procedure InitializeVariabels; virtual;
procedure Execute; override;
public
constructor Create;
property OnTestComplete: TTestCompleteEvent read FOnTestComplete write FOnTestComplete;
end;
procedure TTestThread.DoNotifyTestComplete;
begin
if Assigned(FOnTestComplete) then
// Hier mit Dummy-Werten
FOnTestComplete(Self, FResultText, FAllesOk, 123, 456, False, True, 1);
end;
Im realen Programm für den Endkunden habe ich mehrere "Selbsttests", die beim Programmstart laufen sollen. Thematisch haben diese Selbsttests relativ wenig miteinander zu tun: Der eine holt den freien Festplattenspeicher, der andere überprüft in der Datenbank-Tabelle, ob ungültige Zeitbezüge vorhanden sind, der nächste ob in der Registry unerwartete Werte stehen etc.
Aktuell läuft alles nacheinander, was sich im Laufe der Zeit immer weiter "aufschaukelt", und -je nach Netzwerkgeschwindigkeit- beim Programmstart zwischen 1-2 Sekunden bis zu mehreren Minuten brauchen kann, wenn der Kunde das Programm über eine Bambus-VPN-Leitung startet. Das kann so nicht weitergehen. Ich muss diese ganzen Tests in Threads packen. Das Programm kann/darf auch mit ungültigen Werten starten, die der Selbsttest eigentlich erst finden/beheben soll - das ist kein Problem, denn auch wenn sie beim Programmstart nach dem alten Verfahren hintereinander laufen, wird der Benutzer nur benachrichtigt.
Die Idee ist also, dass alle Tests erzeugt werden, die Testroutine wird über den Thread laufen gelassen (Threadsicherheit bei Datenbankabfragen kommt nun hinzu, CoInitialize etc.!), und sobald fertig wird im
GUI beim entsprechenden Menüpunkt ein grüner Haken oder ein rotes X angezeigt. Die Tests selbst müssen aber (je nach Test) Werte aus dem Thread anzeigen können, damit ich dem Benutzer auch zeigen kann, "was genau" nicht simmt.
Wenn z.B. die Bildschirmauflösung sich von dem Wert in der Datenbank unterscheidet (es gibt eine Bedingung, wann das relevant ist), kommt eine Info an den Benutzer. Er kann nun die Auflösung in der Datenbank auf diesen (oder einen anderen) Wert ändern (neue Auflösung in die Datenbank schreiben; hat nix mit Thread zu tun), und den Test erneut laufen lassen. Da der Thread eh auf die
DB zugreift, sagt er halt nicht nur "Auflösung richtig: Ja/Nein", sondern gibt mir auch die Auflösung, damit ich sie dem Benutzer im
GUI anzeigen lassen kann, ohne sie *nochmals* auslesen zu lassen. Nach dem Ändern der Werte läuft der Thread erneut (Selbsttest), und beim OnTestComplete werden dann die Werte in den Edit-Feldern wieder aktualisiert.
Damit kann erstmal das Programm starten, die Haken für "Ok" oder die X für "Warnung/Fehler" ploppen dann im Menü so nach und nach bei den einzelnen Punkten davon als Grafik auf. Zumindest reagiert das Program in dieser Zeit auf Benutzereingaben.
---
Da mit Threads sehr viel Unglücke passieren können, die man beim Entwickeln nicht unmittelbar sieht (Arbeiten mit TAdoConnection ohne CoInitialize klappt meistens im DebugModus, und ohne Debugger in 70% der Fälle, aber
nicht immer - für diesen und ähnliche Fehler benötigt man Erfahrung und Hintergrundwissen, was ich -in Bezug auf Threads- nicht soooo sicher habe, dass ich mich da jetzt munter in Gefilden bewegen Wollen würde, die dann weitere Probleme verursachen.
> Brauchst du wirklich eine eigene Klasse dafür oder hast du das genommen, weil du TThread nur als abgeleitete Klasse kennst?
Ich nehme an, du redest hier von anonymen Methoden/Threads? ChatGPT schlägt das hier vor, und das würde das Thema ja um den Faktor 100 vereinfachen:
Delphi-Quellcode:
TThread.CreateAnonymousThread(
procedure
var
ResultText: string;
AllesOk: Boolean;
ScreenWidth, ScreenHeight: Integer;
ScreenDimensionMismatch, Vollbild: Boolean;
CurrentMonitor: Integer;
begin
// Beispielhafte Berechnung
ScreenWidth := 1920;
ScreenHeight := 1080;
Vollbild := True;
CurrentMonitor := 1;
ScreenDimensionMismatch := (ScreenWidth <> Screen.Width) or (ScreenHeight <> Screen.Height);
AllesOk := True;
ResultText := 'Test abgeschlossen!';
// Synchronisieren mit Hauptthread und direkt Callback aufrufen
TThread.Synchronize(nil,
procedure
begin
TestAbgeschlossen(nil, ResultText, AllesOk, ScreenWidth, ScreenHeight,
ScreenDimensionMismatch, Vollbild, CurrentMonitor);
end);
end
).Start;
Wäre das in etwa auch dein Vorschlag?
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit