![]() |
Delphi-Version: XE4
For-Schleife im Thread wird nur einmal abgearbeitet
Hi,
ich habe einen Thread, mit eine IdTCPClient, der beim Start ein paar Daten aus dem Hauptprogramm senden soll. Deswegen habe ich dort eine for-schleife, die aus dem Hauptprogramm Daten holt, und per TCP versenden soll. Mir ist schon klar, dass das alles vielleicht noch nicht ganz richtig ist, aber es handelt sich ja hier auch noch nicht um eine finale Version. Ich greife auf eine ListView zu, und will für jedes Items eine TCP-Nachricht verschicken. Im Count steht auch definiv 6 drin, aber die Schleife wird nur einmal durchlaufen. Er senden auch genau dieses erste Item, bzw. einen String aus diesem Items. Aber danach macht er nicht weiter, der Thread scheint auch nicht mehr zu reagieren, jedenfalls empfängt der TCPClient dann keine Nachrichten mehr. Die ganze Writelog's müßt ihr euch mal wegdenken, die sind nur für mich da, damit ich sehen kann wann wer was macht (oder halt eben nicht). Hier mal meine Execute-Procedure:
Delphi-Quellcode:
Sieht alles noch sehr wüst aus, daran bitte nicht stören.
procedure TTCPThread.Execute;
var s,c: string; waage, command: string; i: Integer; begin Try //FTCPClient.BoundIP:=FBindIP; //FTCPClient.BoundPort:=FBindPort; FTCPClient.host:=FHost; FTCPClient.Port:=FPort; FTCPClient.ConnectTimeout:=2000; Synchronize( Procedure begin frm_main.Writelog('Init TCP-Connection'); end ); FTCPClient.Connect; if not FTCPClient.Connected then begin Synchronize( Procedure begin frm_main.Writelog('TCP-Verbindung fehlgeschlagen'); end ); Self.Terminate; end else begin Synchronize( Procedure begin frm_main.Writelog('TCP-Verbindung hergestellt'); end ); //Diese Schleife wird genau einmal durchlaufen //Es sind 6 Items in lv_waagen vorhanden //Es wird aber lediglich lv_waagen.Items[0] verarbeitet FCS.Acquire; for I := 0 to frm_main.lv_waagen.Items.Count-1 do begin Synchronize( Procedure begin frm_main.Writelog('Sende Register '+inttostr(i)+' von '+inttostr(frm_main.lv_waagen.Items.Count-1)); end ); FTCPClient.SendCmd('Register:'+frm_main.lv_waagen.Items[i].SubItems[2]+':@'); end; FCS.Release; end; while not Terminated do begin if FErgebnisList.Count>0 then SendeErgebnisse; if FTCPClient.IOHandler.InputBufferIsEmpty then begin FTCPClient.IOHandler.CheckForDataOnSource(100); FTCPClient.IOHandler.CheckForDisconnect; if FTCPClient.IOHandler.InputBufferIsEmpty then Continue; end; s:=FTCPClient.IOHandler.InputBuffer.ExtractToString; if s<>'' then begin Synchronize( Procedure begin frm_main.Writelog(s + ' von '+ FHost); end ); while Pos('@', s)>0 do begin c:=Copy(s,1,Pos('@',s)-1); s:=Copy(s,Pos('@',s)+1,Length(s)); if Pos(':',c)>0 then begin command:=Copy(c,1,Pos(':',c)-1); c:=Copy(c,pos(':',c)+1,Length(c)); waage:=Copy(c,1,Pos(':',c)-1); if lowercase(command)='st' then begin Synchronize( procedure begin frm_main.NachrichtenBufferAdd(FHost, FPort, s, command, waage, self); end ); end; end; end; end; //Sleep(1000); Self.Suspend; if Terminated then break; end; if FTCPClient.Connected then begin FTCPClient.SendCmd('Disconnect'); FTCPClient.Disconnect; end; finally if FTCPClient.Connected then begin FTCPClient.SendCmd('Disconnect'); FTCPClient.Disconnect; end; FTCPClient.Free; FErgebnisList.Free; FCS.Free; end; end; |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Funktioniert der Code denn auch wenn er nicht innerhalb eines Threads läuft?
Funktioniert es wenn die FCS (Critial Section) nicht benutzt wird? (Diese Critical Section in Verbindung mit einem Synchronize sieht nach einer Deadlockquelle aus). Es ist wahrscheinlich nicht die Ursache für die Hänger, aber FTCPClient.IOHandler.InputBuffer.ExtractToString sieht bedenklich aus, hier kann auch ein Teil des erwarteten Inhalts im InputBuffer stehen. Die Daten können, wenn man das Protokoll kennt, mit IOHandler.Read... Methoden aus dem Socket gelesen werden. Wenn man das Protokoll nicht kennt, hat man ein anderes Problem :) |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Da du im Execute keinerlei Exceptions verarbeitest, solltest du das dringend machen.
Try-Except drumrum und die Exception anzeigen. Tipp: TThread hat ein OnTerminate-Ereignis, welches du dringend mal implementieren solltest, da du Ersteres ja nicht machst. Und da drin dann einfach
Delphi-Quellcode:
Und nicht vergessen, dieser ShowException-Aufruf muß natürlich mit der VCL synchronisiert werden.
if Assigned(TThread(Sender).FatalException) then
ShowException(Exception(TThread(Sender).FatalException), nil); Ex gibt in der Unit System zwar ein End-Thread-Event, aber wenn Dieses ausgeführt wird, dann kann die Thread-Instanz schon weg sein (FreeOnTerminate) und selbst wenn noch nicht, dann kommt man dort sowieso nicht an den Instanzzeiger. :wall: |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Da steht in der Methode ein FCS.Free aber kein FCS := <...>.Create!
Die Mehrfachen blöcke mit
Delphi-Quellcode:
Sollte man mindestens in eine Threadfähige Queue stecken um eine bessere Entkopplung zu haben.
Synchronize(
Procedure begin frm_main.Writelog('....'); end ); |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Zitat:
|
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Hi,
die CriticalSection hab ich erst hinzugefügt, als ich gemerkt habe dass meine Schleife nicht vollständig durchlaufen wird. Vorher gings aber auch nicht. das FTCPClient.IOHandler.InputBuffer.ExtractToString wird mit dem Fehler wohl nichts zu tun haben, denn mein Problem entsteht ja schon vorher. ich kann auch mit 100%Prozentiger Sicherheit sagen, dass sich an meinem ListView während der Thread gestartet wird nicht verändert. Dieses wird aufgebaut, bevor der Thread gestartet wird und auch keiner Stelle im Prog verändert. Interessant finde ich, dass 1. Auf dieses erste Item im LV ohne Fehler zugegriffen werden kann. 2. Auch der korrekte String gelesen wird 3. und diese auch von IdTCPClient korrekt versendet wird. Nur warum es dann nicht weiter geht, das ist mir ein Rätsel. Zitat:
Das mit Assigned(TThread(Sender).FatalException) hab ich grad mal gar nicht verstanden. |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Zitat:
1. Der Thread ist der einzige der darauf zugreift (weil ich nur einen erzeuge) 2. Auf das lv_waagen wird nach dem Füllen nicht mehr zugegriffen, und dieses passiert definitiv vor dem Erzeugen des Threads. |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Mittlerweile habe ich folgendes herausgefunden:
Er bleibt beim FTCPClient.SendCmd hängen, weil: wenn ich die TCP-Verbindung vom Server aus trenne, dann läuft die Schliefe anschließen genau die 6 mal durch, jedoch schlägt dann das senden natürlich fehl. Mit FTCPClient.IOHandler.Writeln läufts dann durch. Durch Try Except hab ich das lokalisieren können. Danke himutsi. Allerdings kann ich nur einmal was empfangen. Also scheint im FTCPClient.IOHandler.InputBuffer.ExtractToString der nächste Fallstick zu liegen. |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Zitat:
Zitat:
Dort gilt das alls GDI-Objekte nur im erzeugten Thread gültig sind. |
AW: For-Schleife im Thread wird nur einmal abgearbeitet
Der Zugriff in der for-Schleife erfolgt eben nicht synchronisiert
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12: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