![]() |
Thread pausieren lassen und aufwecken
Hi Leute, helft mir bitte ...
folgendes, ich habe eine unendliche schleife in ein thread eingebaut, diese schleife prüft eine Variable (hier checkbox1.checked:=true) wenn dise variable true ist, wird in meinem Tread eine Procedure aus eienem anderen Unit gestartet, bevor diese Pocedure startet, wird mein Thread pausiert (Thred.suspend). Nun, wenn die Procedure durchgelaufen ist (checkbox1.checked:=false), will ich das mein Tread weiter läuft und das soll von alleine geschehen (ohne das ich irgendwas mache). Danke!!!
Delphi-Quellcode:
........
unit Tread;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TAnzeigeTread=class(TThread) Sender: TObject; constructor create(CreateSuspended : boolean); virtual; protected procedure execute; override; procedure Doetwas;virtual; abstract; { Public-Deklarationen } end; TForm1 = class(TForm) Edit1: TEdit; Button1: TButton; Edit2: TEdit; Button2: TButton; Button4: TButton; Edit3: TEdit; CheckBox1: TCheckBox; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure etwas(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); private public { Public-Deklarationen } AnzeigeTread:TAnzeigetread; end; var Form1: TForm1; i:integer; a:string; b:boolean; implementation uses Unit2; {$R *.dfm} constructor TAnzeigeTread.create(CreateSuspended : boolean); begin FreeOnTerminate := True; inherited Create(CreateSuspended); end; procedure TAnzeigeTread.Execute; begin i:=0; while(not Terminated)do begin if form1.CheckBox1.Checked then form2.Button1Click(sender); if b=true then form1.Edit1.Text:=a; Form1.etwas(Sender); sleep(50); end; end; procedure TForm1.FormCreate(Sender: TObject); begin b:=true; AnzeigeTread:= TAnzeigeTread.create(true); AnzeigeTread.Resume; end; procedure TForm1.Button1Click(Sender: TObject); begin AnzeigeTread.Suspend; end; procedure TForm1.Button2Click(Sender: TObject); begin AnzeigeTread.resume; end; procedure TForm1.etwas(Sender:TObject); begin i:=i+1; a:=inttostr(i)+'mda'; end; procedure TForm1.Button3Click(Sender: TObject); begin b:=false; end; procedure TForm1.Button4Click(Sender: TObject); begin form2.show; end; end.
Delphi-Quellcode:
unit Unit2;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,tread; type TForm2 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } end; var Form2: TForm2; AnzeigeTread:TAnzeigetread; implementation {$R *.dfm} procedure TForm2.Button1Click(Sender: TObject); begin Form1.AnzeigeTread.Suspend; Form1.Edit3.Text:= 'ok'; Sleep(1000); form1.CheckBox1.Checked:=false; Form1.AnzeigeTread.Resume; // Wie kann ich mein thread weiterfortsetzen???? Form1.Edit3.Text:= 'weiter'; end; end. |
Re: Thread pausieren lassen und aufwecken
Ein paar Fragen zu deinem Code:
1. Warum definierst du den Constructor deines Threads als virtuell? 2. Warum setzt du FreeOnTerminate vor dem Inherited Aufruf im Constructor? 3. Warum deklarierst du eine virtual abstrakte Methode, wenn es keine Ableitung von dem Thread gibt? 4. Wieso greifst du unsynchronisiert auf die Form und deren Komponenten zu? 5. Warum verwendest du die globale Form1 Variable anstatt z.B. eine richtige Instanz dem Thread zu übergeben? 6. Wozu deklarierst du ein Sender: TObject in deinem Thread? 7. Warum benutzt du globale Variablen in dem Thread? 8. Warum vergleichst du eine boolsche Variable auf explizit auf true? 9. Warum legst du den Thread suspended an um ihn dann sofort loslaufen zu lassen? |
Re: Thread pausieren lassen und aufwecken
Die Win32-API-Übersetzung von 'Ich leg mich schlafen und Du weckst mich auf, wenn was los ist' heißt
WaitForSingleObject bzw. WaitForMultipleObject sowie 'Event' oder 'Semaphore'. |
Re: Thread pausieren lassen und aufwecken
Zitat:
Aber ansonsten muss in diesem Thread noch kräftig aufgeräumt werden. |
Re: Thread pausieren lassen und aufwecken
Man kann nicht erwarten, das Einstellungen, die vor einem "Inherited-Create"-Aufruf durchgeführt werden, anschließend noch so vorhanden sind, denn schließlich initialisiert der Create-Aufruf ja alle Eigenschaften. Lieber so:
Delphi-Quellcode:
So ist es imho auch sauberer.
Constructor TMyThread.Create;
Begin Inherited Create (True); // Der Thread schläft MyData.Initialize; // eigene Felder, Daten etc. initialisieren Resume; // und dann, zum Schluß der Initialisierung aufwecken End; ) Wenn man möchte, das ein Thread nur dann etwas macht, wenn z.B. eine Checkbox 'gecheckt' ( :stupid: ) wuirde, dann sollte man im Click-Ereignis der Checkbox den Thread steuern. Ob man das über ein Suspend / Resume, oder mit Hilfe von Synchronisationsobjekten macht, bleibt jedem Selbst überlassen, wobei nur mit den Synch-Objekten gewährleistet ist, das der Thread an einer wohldefinierten Stelle einschläft / aufwacht. Meine Threads sehen eigentlich immer gleich aus (in der Execute-Methode wird gewartet, das etwas passiert). Vielleicht kannst Du dein Problem mit Hilfe eines ![]() |
Re: Thread pausieren lassen und aufwecken
Das mit dem Initialisieren ist ja ein schöner Grund. Aber dies gilt nicht für eigene Felder und auch nicht für TThread (Freeonterminate). Wäre ja auch doof, wenn der Constructor von TThread freeonterminate erst ändert/setzt und dann gleich den Thread startet.
Für den Allgemneingebrauch und wenn man sich keine Gedanken (darüber) beim programmieren machen möchte ist der inherited Aufruf am Anfang der beste Weg. Aber dazu gibt es auch Ausnahmen. Andernfalls hätte man ja die Aufrufreihenfolge des Constructors gleich anders gestalten können. [Edit] Ich sehe grade, dass der Thread eh erst nach dem Constructor gestartet wird (in Afterconstruction). Dann nehme ich alle Aussagen zurück. Dann brauch man allerdings auch nicht inherited mit Createsuspended=true aufrufen und man sollte (trotz dass es in den Demos anders ist) das inherited an den Anfang setzen. [/Edit] Abgesehen von dem, war das einfach eine Antwort auf muetzes Frage, da sich sonst jeder Anfänger (und auch der Threadersteller) fragen wird, warum es Borland denn anders macht (inherited call ans Ende des Constructors). |
Re: Thread pausieren lassen und aufwecken
Zitat:
Das Beispiel, was ich hier reingepostet habe, war eigentlich ein testprogramm, ich versuchte an einem einfacheren Beispiel zu verstehen, wie das ganze funktioniert. Aber nach eueren Antworten sehe ich, dass die sache mit der Checkbox ein totales blödsinn von mir war. In wirklichkeit geht es um ein gerät, das mittels serielle schnittstelle mit meinem programm verbundet ist. An das gerät sende ich in einer unendlichen schleife ein Kommando, was sein Status abfrägt und ein Kommando , was die messdaten am display anfordert. Dieser Schleife ist in einem TTread verkapselt. Das gerät hat zwei Status-Modi... Wenn ich Status-1 abfange, will ich aus der schleife raus, etwas machen, z.B andere Kommandos an gerät senden und von ihm daten empfangen. Wenn diese Porcedure fertig ist, will ich dass die Schleife die Status abfrägt, weiter läuft. Wozu das ganze..so kann ich z.B Tasten-Drück am gerät abfangen und gleichzeitig aktuelle Display -Werte in meinem porgramm zu sehen bekommen. ich habe das ganze bis jetzt ohne suspend ....mit einer StopVariable von typ boolean erledigt es läuft aber irgendwie unsicher...manchmal wenn ich auf dem Form StopTaste oder StartTaste klicke springt der Fokus sofort auf die andere TAste dann wieder zurück... Was ich wollte, dass procedure TMyThreads.Execute sich von alleine schlafen legt und wenn der Code in proceduren Form1.StartTasteClick(Sender) und Form1.StopTasteClick(Sender) bis zur Ende durgelaufen ist..dann weiter läuft.
Delphi-Quellcode:
procedure TMyThreads.Execute;
var Label 10,20,30; begin Form1.Edit11.Text:='Ende'; while(not Terminated)do begin 10:Application.ProcessMessages; If StopVariable=true then begin CP.RTS(1); CP.SENDSTRING('sta,g'+chr(13)+chr(10)); status:=cp.READSTRING(); If trim(Status)='E 01' then goto 10; If trim(Status)='' then goto 10; Form1.Edit6.Text:='begin'; Sleep(100); If (trim(Status)='04') and (StopJa=true) then begin Form1.StopTasteClick(Sender); end; If (trim(Status)='00') and (StopJa=true) then begin Form1.StopTasteClick(Sender); end; If (trim(Status)='02')and (StartJa=true) then begin Form1.StartTasteClick(Sender); end; /// Die letzten aktuellen Messwerten bekommen 20: CP.SENDSTRING('dis,g'+chr(13)+chr(10)); Distanz:=cp.READSTRING(); Distanz:=trim(Distanz); If (length(Distanz)<11) or (length(Distanz)>11) then goto 20; Sleep(50); Test:='okkkkkkkkkkkkkk'; 30: CP.SENDSTRING('kmh,g'+chr(13)+chr(10)); Speed:=cp.READSTRING(); Speed:=trim(Speed); If (length(Speed)<3) and (length(Speed)>5) then goto 30; Form1.Edit6.Text:='untennnnnnnnnnn'; ///* end ; Synchronize(Go); end; end; |
Re: Thread pausieren lassen und aufwecken
Vielen Dank für Ihre Thread Klasse, werde mir unbedingt runterladen und versuchen zu verstehen.
Leider in meinem programm brauche ich keinen code, welcher in Hintergrund was "heimlich" macht.:)) Sonder es geht, um das sicheren Freisetzen der serielle Schnittstelle... ich will das die Prozedur MyThreads.Execute für eine Weile nichts tut . Haben sie vielleicht ein leichverständliches beispiel für WaitForSingleObject??? Kann man vielleicht so machen...das die Prozedur MyThreads.Execute auf eine Variable wartet oder auf die Beendigung der "Stoptaste-Procedure"?? |
Re: Thread pausieren lassen und aufwecken
Das wäre jetzt ein Beispiel für Event und waitforsingleobject. Allerdings habe ich nicht direkt die API-Funktionen benutzt, sondern eine Klasse, die genau diese Funktionen kapselt/benutzt.
Der Thread würde von Button1 gestartet. aber er läuft erst weiter, wenn Button2 gedrückt wurde.
Delphi-Quellcode:
uses ...,syncobjs;
type TmyThread=class(TThread) public protected procedure execute; override; end; type TForm1 = class(TForm) Label1: TLabel; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private-Deklarationen } public { Public-Deklarationen } event:TEvent; end; var Form1: TForm1; implementation {$R *.dfm} procedure TmyThread.execute; var event:TEvent; begin event:=TEvent.Create(nil,true,false,'myEvent'); //Zugriff aus dasselbe Event event.waitfor(infinite); //mach etwas event.free; end; procedure TForm1.Button1Click(Sender: TObject); var thread:TmyThread; begin label1.Caption:='warte'; event:=TEvent.Create(nil,true,false,'myEvent'); //Event anlegen (mit Namen) with Tmythread.Create(true) do //Thread starten begin FreeOnTerminate:=true; resume; end; end; procedure TForm1.Button2Click(Sender: TObject); begin event.SetEvent; event.Free; end; |
Re: Thread pausieren lassen und aufwecken
uf...Danke werde in ein paar stunden ausprobieren :-D :P
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:47 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 by Thomas Breitkreuz