![]() |
AW: 2 Threads starten/pausieren...
Zitat:
Wenn du den Thread später noch ansprechen möchtest, darfst du FreeOnTerminate nicht setzen. |
AW: 2 Threads starten/pausieren...
Zitat:
|
AW: 2 Threads starten/pausieren...
Zitat:
Denn der läuft im Hintergrund und blockiert damit den Haupt-Thread nicht mehr mit zeitaufwändigen Schleifen. Warum soll der nun pausiert werden wenn ein weiterer Thread gestartet wird? Ciao Stefan |
AW: 2 Threads starten/pausieren...
Warum so kompliziert.
Gib doch den einzelnen Datenelementen ein Flag "Hab ich schon" mit. Das wird gesetzt, sobald der Thread das Element verarbeitet hat. Außerdem gibst dem Thread mit, von wo bis wo er arbeiten soll (Standard 0 bis Ende). Dann lass den Thread laufen. Will der User nun plötzlich die Elemente 200-800 verarbeitet haben, gibst dem Thread einfach diese beiden Werte an. Der Thread verarbeitet den laufenden datensatz noch ab und kümmert sich dann um die vorgegebene Range. Durch das markieren mit "Hab ich schon" werden die ja auch kein zweites Mal angefaßt. Hat der Thread seine Range durch (also 200-800 abgearbeitet), gehts einfach wieder von vorn los mit 0-Ende. Durch das "Hab ich schon" arbeitet er dann von ganz allein die ganze Arie ab - selbst wenn der User plötzlich noch 1000-1600 sehen will. Alles in einem Thread, ohne kompliziertes Anhalten/Weiterlaufen/Synchronisieren. |
AW: 2 Threads starten/pausieren...
Zitat:
Es kommt natürlich immer darauf an was man genau braucht, das kann man von außen nicht genau sagen. |
AW: 2 Threads starten/pausieren...
Zitat:
Delphi-Quellcode:
setzen und starten, ohne den Thread zwischenzuspeichern? Das ginge, wenn überhaupt, nur noch entweder im
FreeOnTerminate
Delphi-Quellcode:
(was unsauber wäre) oder mit einem
Execute
Delphi-Quellcode:
(ebenso). Prinzipiell kannst du ihn ja in so vielen Variablen speichern, wie du lustig bist. Du darfst/solltest nur nach dem Starten der Ausführung nicht mehr auf mehr auf das Objekt ohne
with
Delphi-Quellcode:
zugreifen, sofern
try
Delphi-Quellcode:
gesetzt wurde. Davor jedoch kannst du so viel an dem Ding rumspielen wie es dir danach verlangt.
FreeOnTerminate
|
AW: 2 Threads starten/pausieren...
Sorry, aber TRY ...
Man darf NIEMALS wieder darauf zugreifen, sobald der Thread einmal gestartet wurde, egal wo. Ausnahme: Der Thread setzt diese Variable auf NIL, bevor er freigegeben wird. Zugriffe auf diese Variable aber auch nur noch abgesichert, also z.B. innerhalb einer CriticalSection. |
AW: 2 Threads starten/pausieren...
Zitat:
(Ich sehe generell keinen Sinn darin suspended zu erzeugen, egal was für ein Thread das ist. Entweder man braucht den Thread jetzt, dann kann er auch gleich loslegen oder man braucht ihn noch nicht, dann braucht man ihn auch noch nicht erzeugen.) Aber für genau diesen Zweck, ihn nach dem Erzeugen zu starten, kann man eine solche Variable natürlich benutzen. Aber eben danach nicht mehr. |
AW: 2 Threads starten/pausieren...
Hallo,
da sind wir wohl etwas durcheinander gekommen. Oder ich :) Also ich habe einen Thread der mit einer Repeat/Until-Schleife eine reihe von Zahlen durchgeht. Beispielsweise 0-5000. Den erstelle ich inaktiv in meinem Form-Create und mit „FreeOnTerminate = True“ (damit er sich selbst freigibt, wenn fertig). Inzwischen sind es zwei Threads davon, weil es auch zwei Datenhälften gibt, die wechselnd verarbeiten werden sollen. Passt so besser. Die beiden Threads nenne ich jetzt mal die Hauptthreads. Sie werden an einer passenden Stelle im Programm gestartet und kommen auch nur 1x zum starten. Nun greift beispielsweise der Benutzer während die beiden Hauptthreads laufen ein und es wird dann von einer Datenhälfte ein Paket benötigt. (z.b. 3000-4000). Damit alles schneller geht, sollen nun die beiden Hauptthreads Pause machen. Ich habe das nun so gelöst, dass es wiederum zwei weitere Threads gibt, die für die Aktion des Benutzers zuständig ist. Die nenne ich jetzt mal UserThreads. Die sind jedenfalls noch nicht erstellt, sondern werden erst erstellt, wenn der Benutzer die Aktion wählt, sprich das Paket von 3000-4000 als erstes geladen werden soll. Passiert so etwas, dann wird erst mal geprüft ob der Hauptthread für die richtige Datenhälfte überhaupt noch läuft. Ist er nämlich fertig, dann brauch man auch kein Userthread mehr. Diese Prüfung hatte ich mit einem „if .Terminated“ geprüft aber da war ich mir nicht so sicher, da diese Hauptthreads sich selber freigeben und ob man dann mit diesem „Termitated“ darauf noch zugreifen darf, ist mir nicht so ganz klar. Es geht zwar aber ich habe lieber eine globale Variable dafür eingesetzt. Die Benutzer-Aktion (1 von 2) schaut jedenfalls so aus:
Code:
Also beim ersten Mal ist ein „.free“ irgendwie nutzlos aber für weitere Aktionen ist hier dafür der beste Platz. Es macht wohl nichts aus, wenn ein Thread freigegeben werden soll, der gar nicht existiert. Bei einer 2. Aktion vom Benutzer wird er jedenfalls freigegeben und darauf wieder erstellt. So starte ich jedenfalls meine UserThreads. Hier bei den UserThreads habe ich kein „ FreeOnTerminate=True“ gewählt, da sie auch durch eine neue Aktion vom Benutzer abgebrochen werden sollen. Wegen „Priority“… ich muss da noch mal schauen ob das was bringt. In der Execute von UserThread1 (auch im anderen UserThread2) setze ich noch eine globale Varibale „ThreadsPause“ auf „True“, damit die beiden Hauptthreads nicht in der Repeat/Until Schleife weiter hoch zählen. Ist UserThread1 fertig, wird die Variable „ThreadsPause“ wieder auf „False“ gesetzt und die Hauptthreads laufen weiter bzw. sie laufen ja die ganze Zeit aber die Zählervariable dort, wird wieder weiter hochgezählt. Nach der letzten Benutzer-Aktion bleiben ja immer noch zwei UserThreads im Speicher. In meinem Form Destroy gebe ich dann noch die beiden UserThreads frei. So funktioniert das ganze eigentlich recht gut. Natürlich habe ich bei meinen Daten auch ein „hab ich schon“ also als „User[zählervariable].Nummer“ festgelegt. Die Nummer steht auf „-1“ und wenn die Daten verarbeitet wurden, wird diese auf einen anderen Wert (größer als -1) festgelegt. Also wenn der Benutzer ein Paket von 3000-4000 haben will und der Hauptthread ist hier noch nicht angekommen (wird später auf diesen Zahlenbereich kommen), dann ist dies nicht so schlimm. Ich prüfe ja auf den Wert „-1“ und nur dann kommen die rechenintensiven Befehle zum Einsatz. Das Ganze wollte ich ja nur mit einem Thread lösen aber die ganzen Variablen zu setzen (außerhalb) sind schwer im Thread zu prüfen, da der Thread ja läuft und immer wo anders ist, im Execute Bereich (mal Zeile 4, dann 7 und mal Zeile 13). Da macht es sich schwer, ein 0-5000 abzubrechen, dann 3000-4000 durchzugehen, wobei durch einen neuen Abbruch das ganze nur bis 3580 gegangen ist, weil der Benutzer ja schon wieder neue 200-1200 haben will. Dies mit Variablen so zu prüfen, dass sich nichts in die quere kommt, ist echt schwer. Bestimmt gibt es da Lösungen/Befehle etc. denn es gibt ja nicht nur „Execute“. Es sind ja auch meine ersten Erfahrungen mit Threads und so wie ich es jetzt habe, gefällt es mir natürlich dann… weils halt geht :)
If HThread1Finish = False Then
Begin UserThread1.free; UserThread1 := TUserThread1.Create(true); UserThread1.FreeOnTerminate := false; Userthread1.Priority := tpTimeCritical; UserThread1.iv := startzahl // z.B. 3000 UserThread1.ib := enddzahl // z.B. 4000 UserThread1.Start; End; Ich hoffe es ist nun verständlich wie ich so meine Threads einsetze und zu welchem Zweck. Ich fülle Daten Records mit Werten, die dann zur Ansicht kommen. 2-3 Befehle (um mein Daten Record zu füllen) kosten dann etwas Zeit und damit der Benutzer auf diese Ansicht nicht warten muss, brauche ich dann diese Threads… die sicherlich besser gelöst werden können aber ich halt noch kein Durchblick dazu habe. :) Michael |
AW: 2 Threads starten/pausieren...
Klingt kompliziert, habs jetzt nicht komplett nachvollzogen was du machst ...
Ich würde einfach zwei Threads über Events steuerbar machen, so ![]() Dann könntest du die Threads intern immer laufen lassen, und ja nach Guste über die Events stillegen oder freischalten. Dann braucht man kein "Terminate" (nur am Programende, und keine globalen Variablen. Rollo |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:05 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