![]() |
2 Threads starten/pausieren...
Hallo,
ich habe derzeit einen Thread den ich folgendermaßen aufrufe.
Code:
An einer späteren Stelle mache ich dann Thread1.Resume.
Thread1 := TSelfThread.Create(True);
Thread1.FreeOnTerminate := True; In der Execute Prozedur gehe ich eine For-Schleife durch. Wenn die fertig ist, beendet sich der Thread ja automatisch. Solange der erste Thread läuft (also die For-Schleife noch nicht ferig ist), bräuchte ich eigentlich einen zweiten Thread, der evtl. ab und zu gestartet werden muss. Wenn der zweite Thread gestartet wird, soll sich der erste Thread kurz schlafen legen, also die For-Schleife soll auch pause machen. Wenn der zweite Thread (hier wird es auch eine For-Schleife geben) fertig ist, soll der erste Thread und die For-Schleife weiter laufen. Der zweite Thread muss nie pausiert werden, eher vorzeitig beendet und wieder neu gestartet werden, um hier andere Werte (von - bis) bei der For-Schleife durchzugehen. Wenn der erste Thread (also die For-Schleife) komplett fertig ist, muss der zweiter Thread nicht mehr gestartet werden. Kann man das realisieren? Michael |
AW: 2 Threads starten/pausieren...
Zitat:
|
AW: 2 Threads starten/pausieren...
Also ich möchte im Thread wenige Prüfungen machen, damit er schnell bleibt.
Ich habe im Thread beispielsweise eine For-Schleife von 0-5000, in der ein Programmcode abgearbeitet werden muss. Für die aktuelle For-Zahl kann ich jedenfalls prüfen, ob der Programmcode auch wirklich abgearbeitet werden muss (also er müsste eigentlich nicht beendet werden), denn je nach Benutzeraktion muss evtl. vorzeitig 250-500 oder 3000-4000 von der For-Schleife verarbeitet werden. Ich muss eigentlich im Hauptprogramm je nach Benutzeraktion zwei Variablen "von" und "bis" festlegen, die etwas Zeit benötigen und dachte deshalb an einen zweiten Thread. Michael |
AW: 2 Threads starten/pausieren...
Ich habe mir gerade folgendes für die Execute überlegt (ungetestet).
Müsste nur dann im Hauptprogramm wenn erforderlich die Variablen "von", "bis" und "check" setzen. Während meine 5000 (hier jetzt repeat/until) abgearbeitet werden, wird ja geprüft ob vorzeitig ein anderer Zahlen-Abschnitt gebraucht wird. Man muss nur schauen, dass man keine i-Zahl auslässt und eigentlich schon abgearbeitete nicht mehr erneut abgearbeitet werden.
Code:
Kann ich die Variablen "von", "bis" und "check" einfach setzen?
repeat
i = i +1; if check = true then begin if isave = -1 then begin isave = i; i = von; end; end; daten[i]... if check = true then begin if i = bis then begin i := isave; check := false; end; end; if i=5001 then ok := true; until ok=true So vielleicht:
Code:
Und im Hauptprogramm, während der Thread läuft dann irgendwo wenn gewünscht einfach...
type
TThread1 = class(TThread) private von,bis : integer; check : boolean; public procedure Execute; override; end;
Code:
Michael
Thread1.von := 50;
Thread1.bis := 100; Thread1.check := true; |
AW: 2 Threads starten/pausieren...
Und wieso benutzt du dann nicht einfach wei unterschiedliche Routinen für den selben Thread? So bekommst du es dann ohne Überpfüfungen hin...
Delphi-Quellcode:
EDIT: Kannst du natürlich auch mit anonymen Methoden machen, falls dein Delphi das unterstützt. Hab ich allerdings weggelassen, denn ansonsten könntest du ja auch direkt
type
TMyThread = class(TThread) private procedure First; procedure Second; protected ExecutionRoutine: TProcedure; public procedure Execute; override; end; procedure TMyThread.Execute; override; begin while not Terminated do begin ExecutionRoutine; end; end; procedure TMyThread.First; begin //Falls (nicht B), unterbreche für zweite Routine if not B then begin ExecutionRoutine := Second; end; end; procedure TMyThread.Second; begin //Nach Beendigung wieder erste Routine ExecutionRoutine := First; end;
Delphi-Quellcode:
nehmen.
TThread.CreateAnonymousThread(...)
|
AW: 2 Threads starten/pausieren...
Das würde ich anders lösen. Ich würde das ganze in Pakete aufteilen, die abzuarbeiten sind. Die Größe der Pakete hängt davon ab wie lange es dauert diese zu bearbeiten. Auf die Weise kannst du schnell unterbrechen, auch wenn immer das komplette Paket bearbeitet wird.
Die einzelnen Pakete kannst du dann in eine Queue packen, der Thread holt sich dann jeweils immer das nächste Paket heraus. Die Queue muss natürlich threadsicher sein. Von außen kannst du nun einfach Einfluss auf die Abarbeitung der Pakete nehmen, z.B. indem du ein Paket an Platz eins setzt und so weiter. Auf die Weise kannst du einzelne Pakete priorisieren oder nach hinten schieben. |
AW: 2 Threads starten/pausieren...
Zitat:
|
AW: 2 Threads starten/pausieren...
Danke für die Vorschläge.
Noch etwas schwer für mich... mit first/second oder Queue-Dingsbumbs :) Meine eigene Überlegung mit dem Code den ich hier aufgeschrieben habe, ist auch nicht so einfach. Da muss man aufpassen denn sobald die Variablen außerhalb des Threads gesetzt werden, werden diese ja auch im Thread übernommen. Da kommt es dann drauf an, wo der Thread gerade die Zeile verarbeitet. Dennoch habe ich damit weiter probiert und habe es jetzt so:
Code:
Außerhalb des Thread setzte ich dann nach Benuteraktion:
iV := 0; // Originale Start-Zahl (immer 0)
iB := Length(FDR)-1; // Originale End-Zahl (z.B. bis 5000) i := 0; // Ab 0 beginnen userpos := false; // False = normaler Durchgang repeat daten[i]... i := i + 1; if ucheck = true then begin iv := i; i := uiv; ib := uib; if ib > Length(FDR)-1 then ib := Length(FDR)-1; ucheck := false; userpos := true; end; if userpos = true then begin if i>= ib then begin i := iv; ib := Length(FDR)-1; userpos := false; end; end; until i >= ib;
Code:
So geht es einigermaßen aber der Thread wird nicht beendet, wenn der Benutzer ständig Aktionen durchführt. Da muss ich noch rumbasteln. Aber so im Ganzen ist es wohl auch nicht optimal, wenn ich gerade drüber nachdenke.
Thread1.uiv := neue_start_zahl; // z.B. 200
Thread1.uib := neue_end_zahl; // z.B. 1000 Thread1.ucheck := true; Eigentlich soll es so sein: Der Thread soll halt ganz normal von 0-5000 (als Beispiel) die Schleife verarbeiten. Kommt der Benutzer und will (200-1000) dann sollen diese erster verarbeitet werden. Sind diese aber schon durch von der normalen Schleife 0-5000 dann müssen diese 200-1000 nicht verarbeitet werden. Der Benutzer kann jedenfalls zwischen dieser Zeit 200-1000 wieder eine neue Aktion durchführen und will 3000-4000 haben, diese dann aktuell verarbeitet werden sollen, solange diese nicht schon von der normalen Schleife verarbeitet wurden. Ich hoffe das ist verständlich :) Zum Glück sind meine "daten[i]..." Sachen (es ist ein Record) so aufgebaut.
Code:
Also es ist nicht so ganz schlimm, wenn die Schleifenzahl schon mal genutzt wurde.
nr := daten[i].nummer;
If nr = -1 Then Begin // ... Daten werden verarbeitet, gesetzt, gespeichert usw. // und das kostet etwas mehr zeit (mal 1 sek, mal 5 sek. je nach Inhalt, der immer anders sein kann) daten[i].nummer := zahl größer -1; End Ich kenne mich noch nicht so aus mit den Threads und was man alles so damit machen kann. Deswegen denke ich, es wäre der beste Weg, man hat einen Thread für die 0-5000 und ein weiteren Thread für die Benutzeraktion. Wenn der Benutzer-Thread ausgeführt werden soll, soll der 0-5000 Thread pause machen. Das könnte man ja so realisieren, dass die Schleifenzahl nicht weiter hochzählt. Ist der Benutzer-Thread fertig, dann wird die Schleifenzahl vom normalen 0-5000 Thread wieder weiter hochgezählt. Ob nun bei dem einem Thread oder beim anderen die daten[i]... schon verarbeitet wurden oder nicht, wäre ja nicht so schlimm, da ich dieses ja mit "nr := daten[i].nummer" auf "-1" prüfe. Ich habe schon gelesen, dass es nicht so optimal ist, wenn man Threads pausieren lässt und wieder startet. Wie gesagt, bei dem normalen 0-5000 Thread könnte ich ja zum Pausieren die Schleifenzahl nicht hochzählen lassen und ein Benutzer-Thread erstellen. Ist der Benutzer-Thread fertig, wird er einfach freigegeben. Wenn der normale 0-5000 Thread durch ist und beendet wurde, muss kein Benutzer-Thread mehr erstellt werden (da ja alles von den 0-5000 durch ist). So meine Überlegungen :) Michael |
AW: 2 Threads starten/pausieren...
Zitat:
Zitat:
Zitat:
|
AW: 2 Threads starten/pausieren...
Ich habe es jetzt so.
Den 0-5000 Thread erstelle in meinem OnCreate von der Form und setzte "Thread1.FreeOnTerminate := true;". "Thread1.Start" kommt an einer anderen Stelle zum Einsatz. Der geht nun ganz normal durch (mit Repeat/Until-Schleife) und wird nach beenden freigegeben. Der wird auch nicht pausiert. Aber das würde ich noch gerne einbauen. Daran versuche ich mich gleich. Der Benutzer-Thread erstelle ich so:
Code:
Solange der Thread1 (0-5000 Thread) läuft, kann ein UserThread erstellt werden.
if Thread1.Terminated = False Then
Begin UserThread.free; UserThread := TUserThread.Create(true); UserThread.FreeOnTerminate := false; UserThread.iv := UserStartZahl; UserThread.ib := UserEndZahl; UserThread.Start; End; UserThread.free brauche ich ja hier nicht prüfen oder? Wenn gerade ein UserThread läuft, wird durch "UserThread.free" dieser ja beendet und freigegeben. Wenn keiner läuft, geht "UserThread.free" ja auch, also es machts nichts, wenn keiner freigegeben werden muss. In der Execute von UserThread läuft dann eine For-Schleife (i := iv to ib) ab. So funktioniert es jedenfalls. Michael |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:11 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