![]() |
Thread mit Überwachungsfunktion wird blockiert
Hallo und guten Tag an alle,
ich hab mal wieder eine Frage bezüglich TThread. Und zwar habe ich in Bezug auf diesen ![]() Bevor ich zur Problembeschreibung komme hier mal mein Thread-Rumpf, den ich nach einer Vorlage hier aus der DP genommen hab:
Delphi-Quellcode:
Ok zuersteinmal, weiß ich sicherlich nicht, ob diese Variante des Threads wirklich sehr "gelungen" ist. Weiß aber derzeit nicht, ob es eine bessere Alternative zu dem Timer gibt, den ich für die zyklische Abfrage meines digitalen Einganges gibt (Vorschläge werden gern angenommen).
unit SteuerkartenKontrollThread;
interface uses Classes, ExtCtrls; Type TOndigEingang = procedure(Sender: TObject; iChannel: integer) of Object; TOnanaEingang = procedure(Sender: TObject; iChannel, iWert: integer) of Object; Type TControlCardControlThread = class(TThread) private Timer: TTimer; FOndigEingang: TOndigEingang; FOnanaEingang: TOnanaEingang; protected procedure Waechter(Sender: TObject); procedure Execute; procedure dodigEingang(iChannel: integer); procedure doanaEingang(iChannel, iWert: integer); public constructor create; reintroduce; destructor destroy; override; property OndigEingang: TOndigEingang read FOndigEingang write FOndigEingang; property OnanaEingang: TOnanaEingang read FOnanaEingang write FOnanaEingang; end; implementation uses Steuerkarte; constructor TControlCardControlThread.create; begin inherited create(false); Timer := TTimer.Create(nil); Timer.Enabled := true; Timer.Interval := 50; Timer.OnTimer := Waechter; // weitere Kommandos end; destructor TControlCardControlThread.Destroy; begin Timer.Free; inherited destroy; end; procedure TControlCardControlThread.Execute; var iIndex: integer; begin Timer := TTimer.Create(nil); Timer.Enabled := true; Timer.Interval := 50; Timer.OnTimer := Waechter; end; procedure TControlCardControlThread.Waechter(Sender: TObject); begin if ReadDigitalChannel(2) then dodigEingang(2); //hier wird derzeit eins von mehreren Events initialisiert // funktioniert end; procedure TControlCardControlThread.dodigEingang(iChannel: Integer); begin if assigned(FOndigEingang) then FOndigEingang(Self, iChannel); end; procedure TControlCardControlThread.doanaEingang(iChannel: Integer; iWert: Integer); begin if assigned(FOnanaEingang) then FOnanaEingang(Self, iChannel, iWert); end; end. Jetzt zu dem Problem. Die digitalen Eingänge sitzen auf einem Controlerboard, welches mir den Strom für die weitere Perepherie-Geräte freischaltet (und natürlich auch wieder ausschaltet). Dies funktioniert auch sehr gut, wenn das Programm läuft. Allerdings wenn das Programm startet, reagiert er überhaupt nicht. Woran das liegt kann ich mir in einem gewissen Rahmen auch denken. Habe ein Splashscreen, welches in einer Schleife "ein- und ausgeblendet" wird und es werden weitere Perepherie-Geräte initialisiert. Wie kann ich jetzt auch bei der Implementierung das Programm dazu zwingen auf die Events, die in meinem Thread erzeugt werden zu reagieren. Ich weiß ich kann Application.ProcessMessages verwenden, was mir aber nur in Teilen hilft. Z.B. wenn das im Ein- und Ausblenden der Splashscreen steht, führt es zu regelmäßigem Einfrieren des Programmes, welches nur durch das rote viereckige Kästchen in Delphi beendet werden kann. Weiterhin müssten ja grundsätzlich dann in jede Procedure welche nach dem ControlerBoard ausgeführt wird diese Application.ProcessMessages aufgerufen werden, was ein erheblicher Arbeitsaufwand wäre. Gibt es irgendwelche anderen Möglichkeiten, das Programm zum Reagieren zu zwingen? Vielen Dank BAMatze |
Re: Thread mit Überwachungsfunktion wird blockiert
erstmal erstellst du 2 Timer :!:
einmal in .Create und nochmal in .Execute dann braucht ein Timer eine Nachrichtenschleife und dein Thread hat keine Delphi hat bei sich im Hauptthread eine laufen, aber da du den Timer in deinem Thread erstellst, werden die Timer-Nachrichten an diesen Thread gesendet und von dir nicht verarbeitet, also wird auch die Timer-Ereignisprozedur nicht aufgerufen. |
Re: Thread mit Überwachungsfunktion wird blockiert
Hi,
ein Timer im Thread macht IMHO wenig Sinn. Machs lieber mit einer While-Schleife in Execute; deines Threads. Im Ereignis dodigEingang hast du bestimmt Code deines Hauptprogramms stehen, oder? Dann musst du dieses Ereignis synchronisieren:
Delphi-Quellcode:
Synchronize(dodigEingang);
|
Re: Thread mit Überwachungsfunktion wird blockiert
Zitat:
Hast du eventuell für mich eine Möglichkeit, wie ich das lösen kann (eventuell einen kurzen Beispielcode oder Link)? Wüsste so derzeit nicht direkt, wie ich das lösen könnte :lol: Vielen Dank BAMatze |
Re: Thread mit Überwachungsfunktion wird blockiert
Vielleicht läßt es sich so lösen:
Delphi-Quellcode:
Grüße
procedure TControlCardControlThread.Execute;
begin while not terminated do begin sleep(50) // Dein Interval waechter; // das was du alle 50ms tun willst // wenn waechter auf die GUI zugreift dann // synchronize(waechter); end; end; Klaus |
Re: Thread mit Überwachungsfunktion wird blockiert
Zitat:
|
Re: Thread mit Überwachungsfunktion wird blockiert
Delphi-Quellcode:
aber ich würde auch keinen Timer verwenden,
constructor TControlCardControlThread.create;
begin inherited create(false); Timer := TTimer.Create(nil); // hier nur alles erstellen end; destructor TControlCardControlThread.Destroy; begin Timer.Free; inherited destroy; end; procedure TControlCardControlThread.Execute; var iIndex: integer; begin // hier alles starten Timer.Enabled := true; Timer.Interval := 50; Timer.OnTimer := Waechter; // und jetzt hier noch eine Nachrichtenschleifen hin // zu finden z.B. in Luckies NonVLC-Tutorials // aber keine via Application.irgendwas, sondern direkt über die WinAPI // und vergiß nicht eine nette Abbruchbedingung für // diese "Endlos"-Schleife zu definieren end; sondern via Sleep arbeiten ... also in .Execute
Delphi-Quellcode:
Sleep(50) wenn immer 50 ms Pause dazwischen sein soll
var c: Integer;
repeat c := GetTickCount; if ReadDigitalChannel(2) then dodigEingang(2); ... c := {interval}50 - (GetTickCount - c); if c > 0 then Sleep(c); until Terminated; und so wie oben wird die Bearbeitungsdauer gemessen (also wenn es auch mal etwas "länger" dauern kann und dann nur noch die Restzeit gewartet |
Re: Thread mit Überwachungsfunktion wird blockiert
Wenn wirklich sofort auf das Ereignis reagiert werden soll, darf Synchronize nicht verwendet werden.
Sonst wartet auch der Thread auf das nächste ProcessMessage. Deshalb muss die aufgerufene Methode wirklich vollständig threadsicher sein (auch Zugriffe auf Klasseneigene Property). Die Methoden doanaEingang und dodigEingang und Zugriffe auf FOndigEingang und FOnanaEingang sind ebenfalls noch nicht threadsicher. |
Re: Thread mit Überwachungsfunktion wird blockiert
Fehlt da nicht ein override?
Delphi-Quellcode:
Type TControlCardControlThread = class(TThread)
private Timer: TTimer; FOndigEingang: TOndigEingang; FOnanaEingang: TOnanaEingang; protected procedure Waechter(Sender: TObject); procedure Execute; override; // <-- HIER procedure dodigEingang(iChannel: integer); procedure doanaEingang(iChannel, iWert: integer); public constructor create; reintroduce; destructor destroy; override; property OndigEingang: TOndigEingang read FOndigEingang write FOndigEingang; property OnanaEingang: TOnanaEingang read FOnanaEingang write FOnanaEingang; end; Ist das nicht besser so, anstatt mit Timer?
Delphi-Quellcode:
procedure TControlCardControlThread.Execute;
var iIndex: integer; begin while no Terminated do begin Waechter; //Waechter muss natürlich angepasst werden wegen Sender: TObject. Sleep(50); end; end; |
Re: Thread mit Überwachungsfunktion wird blockiert
Also hab jetzt mal angefangen mit Luckie´s Tut für nonVCL das mit dem WinProc mir anzueignen. Einiges hab ich schon verstanden, allerdings sind noch gerade für die Umsetzung einiges an Fragen offen. Werde mir das ganz aber erstmal weiter bis in die Tiefe zu Gemüte führen. Hoffe dadurch erledigen sich noch einige der offenen Fragen.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz