Thread mit timer gestartet
Hallo
Mein Thread liest Daten von der Comport und schreibt sie in verschiedene globale Variablen. Das funktioniert mit einer endlose Schleife im Thread. Das ist aber sicher nicht die beste Lösung. Ich möchte lieber, dass es periodisch alle 200mS passiert. Wenn ich mit der Componente Timer (gestartet im Form1) das Thread starte, funktioniert es nur so lang Form1 aktiv ist. Beim Wechsel in Form2 läuft der Timer nicht mehr und somit wird auch der Thread nicht gestartet. Ja nun, wie lässt es sich machen, dass sich der Thread alle 200mS selber startet und zwahr unabhängig davon in welche Form x ich mich gerade befinde? Im meinem Programm wird es vermutlich 8 verschiedene Menüs geben => jeweils andere Forms. Und wie lässt es sich machen das möglichst wenig Rechenzeit verbraucht wird während der Wartezeit ? Eine endlose schleife mit sleep im thread-execute ist vermutlich nicht die beste Lösung, oder ? |
AW: Thread mit timer gestartet
Zitat:
|
AW: Thread mit timer gestartet
Der Timer braucht ja ein Window-Handle mit dem er dann läuft. Deswegen scheidet die Möglichkeit schonmal aus, einen Timer im Thread zu erstellen.
Ich habe das in einem Projekt bei mir genauso gemacht. In einer Schleife im Thread.Execute wird eine Funktion aufgerufen, die z.B. Daten einliest, und wenn die Funktion durch ist, dann rufe ich ein Sleep auf, und warte einige Zeit. Wenn das Sleep zurück kommt, dann läuft die Schleife weiter. Und damit wäre Dein Thread autark und läuft eigenständig in einer Schleife. Irgendwie sowas:
Delphi-Quellcode:
procedure TMainThread.Execute; begin FreeOnTerminate := False; Try While Not Terminated do Begin meineEinleseFunktion; // <---- Hier wird die Funktion aufgerufen, die die Daten einlesen soll Sleep(5000); End; Except On E:Exception do ; // TODO: Exception logging... End; Terminate; end; |
AW: Thread mit timer gestartet
Es gibt sicher bessere Lösungen, aber ohne das Programm jetzt komplett umzustellen könnte man den Timer einfach in ein Datenmodul verschieben.
Das lässt man beim Programmstart erstellen und ist immer da, egal welche Formulare angezeigt werden. |
AW: Thread mit timer gestartet
Die Idee ist doch 'alle x ms Daten zu lesen'. Was spricht dann gegen das 'Sleep' in der Bearbeitungsschleife, wie von Bowler skizziert?
|
AW: Thread mit timer gestartet
Dafür gibt es in der Kernel32 die API SetWaitableTimer
Diesen Timer kann man dann innerhalb Thread.Execute erstellen. Sleep ist immer eine schlechte Idee. gruss |
AW: Thread mit timer gestartet
Warum ist sleep eine schlechte Idee?
Wenns nicht der Hauptthread ist dann friert nichts ein und während dem sleep kann sich der Prozessor um andere Prozesse/Threads kümmern wodurch Resourcen gespart werden. |
AW: Thread mit timer gestartet
Zitat:
Ich verwende lieber meine Methode da ich dann von zeit zu zeit Einfluss nehmen kann auf den Thread, wann eine Aktion ausgeführt werden soll. Nicht jede Form oder Aktion benötigt eine Wartezeit von 200ms. Das bremst unterumständen das Programm aus. PS: Wenn innerhalb des Threads auf Funktionen der GUI (Form) zugegriffen wird friert das Programm für 200ms ein. Aber jeder wie er will. gruss |
AW: Thread mit timer gestartet
Zitat:
|
AW: Thread mit timer gestartet
Zitat:
Dein Thread hat nichts mit dem der GUI gemein. Jetzt versuche mal aus deinen Thread einen Label aus der GUI anzusprechen so das er alle 10ms die neue Zeit anzeigt. Ich denke das dein Thread das Programm einfriert und der Label in dem Fall nicht aktualisiert wird. Versuchs doch einfach. gruss |
AW: Thread mit timer gestartet
Delphi-Quellcode:
im Thread und ich bin ziemlich sicher dass es gehn wird :wink:
while true do
begin Synchronize(LabelSetzen); sleep(10); end; Edit: Ausprobiert - klappt ohne einzufrieren oder sonstige Probleme. |
AW: Thread mit timer gestartet
Na gut ich kenn es anders..
GUI-Elemente dürfen nur im Hauptthread erzeugt und angesprochen werden.. siehe Invoke! Alles andere friert den Hauptthread ein. Aber vielleicht verwechsle ich da auch was.:!: War auch nur ein Vorschlag ob er nun Sleep verwendet oder meinen Vorschlag sei ihm überlassen. Bei mir ist Sleep die allerletzte Entscheidung wenn es nicht mehr anders geht. gruss |
AW: Thread mit timer gestartet
Naja wenn man ohne Synchronize auf die GUI des Hauptthreads zugreift kann es zu Fehlern und ggf. Absturz des Nicht-Hauptthreads führen falls beide Threads plötzlich gleichzeitig auf GUI-Elemente zugreifen. Es friert eigentlich nichts ein. Wäre das sleep(10) nicht im Thread dann würde der Main Thread einfrieren weil Synchronize die entsprechende Methode im MainThread ausführt und das den Thread quasi unnötig machen würde. So führt er das setzen des Labels im MainThread aus, kehrt zurück, wartet 10 MilliSekunden und wiederholt das ganze. Ist also in dem Fall einfach nur eine Art übermäßig komplizierter Timer.
|
AW: Thread mit timer gestartet
Zitat:
Aber du meinst wohl 10ms.. Flüchtigkeitsfehler. :) gruss |
AW: Thread mit timer gestartet
Eh ja genau, habs korrigiert :mrgreen:
|
AW: Thread mit timer gestartet
Zitat:
Ok das musste sein ;) gruss |
AW: Thread mit timer gestartet
Man hätte auch einfach den Code ändern können ;)
Delphi-Quellcode:
sleep(10000);
|
AW: Thread mit timer gestartet
Zitat:
gruss |
AW: Thread mit timer gestartet
Hallo,
Danke für die viele Beiträge. Wenn ich Euere Diskusion richtig verstanden habe, darf man den sleep verwenden wenn man im Thread keine GUI funktionen braucht. Das ist auch bei mir der Fall. Sonst muss man die API funktion benützen, ist noch wichtig das zu wissen ! |
AW: Thread mit timer gestartet
Nicht ganz. Sleep geht immer. Auf die GUI sollte man eigentlich überhaupt nicht aus einem Thread zugreifen, wenn alle Stricke reißen aber bitte dann synchronisiert. Besser aber gar nie und nimmer, das zwingt einen auch gleichzeitig zu einem vernünftig entkoppelten Programmdesign. Ich nutze Sleep() auch sehr viel in Threads, und halte es für eine absolut gängige Methode wenn sichergestellt ist, dass man seinen Thread nicht doch event-gesteuert auch mal zwischen durch beleben möchte. (Wobei ich es auch wieder in die Design-Problem Ecke stellen würde, wenn man EINEN Thread hat, der sowohl zyklisch als auch nach Ereignissen reagieren soll.)
Dass ein Sleep nicht mit in den synchronisierten Abschnitt gehört, sollte eigentlich klar sein. Ansonsten: Schlaf gut! |
AW: Thread mit timer gestartet
Nein. Du kannst Sleep in einem Thread verwenden, auch wenn Du (natürlich indirekt, z.B. über Synchronize) auf GUI-Elemente aus dem Thread heraus zugreifst. Das macht überhaupt nichts.
Na ja, und so ein kleiner Backgroundworker in einem LOB-Tool, was man so mal eben schreibt, verletzt nur heimlich irgendwelche Designregeln. So zum runterschruppeln eines kleinen Tools ist das vollkommen ok. |
AW: Thread mit timer gestartet
Hallo alle... :hi:
Ein Sleep im Thread ist zwar möglich, behindert im Normalfall auch nicht den Mainthread. Die Spreu trennt sich beim Beenden des MainThreads vom Weizen. Da wartet der Mainthread auf die Beendigung des Sleep des Threads...und der Benutzer wundert sich. :P Lektüre für selbiges Problem: http://www.delphipraxis.net/181596-p...m-tthread.html einfache Lösung in #4 |
AW: Thread mit timer gestartet
Zitat:
Wie Medium schon schrieb! Zitat:
Ich würde es grundsätzlich verneinen. (Zumindest in meinem Fall) gruss |
AW: Thread mit timer gestartet
Sinngemäß:
Delphi-Quellcode:
ThreadExecute;
while not Terminated then begin // mach was Sleep(50000); end;
Delphi-Quellcode:
Frage: Wie lange dauert das Beenden?
procedure Form1.FormClose;
begin Thread.Terminate; Thread.Waitfor; Thread.Free; // wo auch immer. end; PS: Wir sprechen nicht über Abwürgen sondern definiert Beenden. :zwinker: |
AW: Thread mit timer gestartet
Geht irgendwie am Thema vorbei.
Ich sagte doch Verwendungsabhängig. Ich habe ein Plugin System in dem die Plugins selbst das verhalten und Aktualisierung des Threads beeinflussen. Was soll ich da mit einem Sleep? Das blockiert nur die Anwendung. Die Plugins legen also fest mit welchen Intervall der Thread aktualisiert (Timer abhängig). Wie das bei ihm ist entzieht sich meiner Kenntnis aber verallgemeinern kann man das nicht. Sleep or not Sleep das ist hier die Frage! ;) gruss |
AW: Thread mit timer gestartet
Gut, in meinen Fällen bewegt sich die Wartezeit selten über 1000ms. Das ist in der Tat ein valides Problem. Aber auch "schmutzig" lösbar:
Delphi-Quellcode:
Nicht schön, aber möglich.
procedure TMyThread.Execute;
var timer: Integer; begin repeat // Zeug timer := 0; repeat Sleep(100); inc(timer, 100); until (timer >= 1000) or Terminated; until Terminated; end; In meinem letzten Thread-intensiven Projekt habe ich es noch ein wenig anders: Es gibt einen Haupt-Workerthread, dessen Aufgabe es ist Jobs abzuarbeiten (Einträge in eine DB machen). Die Jobs fallen zyklisch an, wobei es mehrere verschiedene Zyklus-Gruppen gibt, die alle unterschiedliche Intervalle haben. Für jede Gruppe gibt es daher einen weiteren Thread, der einfach nur seine Wartezeit durch wartet, und dann dem Job-Thread signalisiert einen Job zu machen.
Delphi-Quellcode:
(Das Sleep(0) sorgt dafür, dass der Thread immer mal wieder seine Time-Slices abgibt, und damit nicht immer maximale CPU Auslastung verursacht.)
// "Timer-Thread"
proceudre TJobGroup.Execute; begin repeat while ((GetTickCount-LastJobFired) < Interval) and (not Terminated) do Sleep(0); if not Terminated then SignalJob(); LastJobFired := GetTickCount; until Terminated; end; // Job-Thread procedure TJobs.Execute; begin repeat while JobList.Count > 0 do begin DoStuff(JobList[0]); JobList.Delete(0); end; Sleep(0); until Terminated; end; Die JobList Zugriffe müssen natürlich durch eine CriticalSection gesichert werden. Aber das ist schon für ein recht großes Projekt, für ein Töölchen so nebenbei würde ich das so auch nicht machen. |
AW: Thread mit timer gestartet
Hallo
Ich habe offenbar mit meinem Thema eine kontroverse Diskusion angeworfen. Besten Dank für die vielen Beiträge, ich habe daraus einiges gelernt. Die Verwendung von "sleep" in Threads ist u.U. doch nicht ganz harmlos. Gruss Anton |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:18 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz