Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Thread und Indy - Programmabsturz (https://www.delphipraxis.net/58084-thread-und-indy-programmabsturz.html)

Riese 1. Dez 2005 08:33


Thread und Indy - Programmabsturz
 
Hallo zusammen,

setze seit kurzem die Indy Komponenten ein.
Dabei vor allem die TIdTCPClient Komponente mit der ich einen Server kontaktiere.

Dabei liegt die Komponente auf einem Formular Form1.

Ich habe einen von TThread abgeleiteten Thread.

Im Thread lese ich mittels IdTCPClient1.ReadBuffer aus dem Client.

Je nach übermitteltem Kommando reagiere ich entsprechend im Thread.
Im Thread benutze ich dann zum Schreiben in ein Memo-Feld auf Form1 die Synchronize Methode.

Geht alles. Aber wenn ich mein Programm beende wird nur das Hauptformular Form1 beendet. Der Thread wird nicht beendet. Ich habe in OnFormDestroy (Form1) einen Aufruf myThread->Terminate drin.
Aber der funktioniert nicht da ich im Thread Terminated zwar abprüfe aber der Thread ja noch beim Einlesen von der IndyKompo hängt.
Denkt ihr dass ein TIdTCPClient-Timeout das Problem löst?

Manchmal kommt es auch vor, dass direkt nach dem Programmende der Thread abstürzt. Wie ist denn das mit Synchronize? Braucht man das beim Zugriff auf alle Komponenten auf dem Hauptformular oder nur bei den sichtbaren. Muss man also den Zugriff auf meine Form1.IdTCPClient1 Komponente auch in Syhronize kapseln?

Gruß und Danke
Riese

FriFra 1. Dez 2005 09:17

Re: Thread und Indy - Programmabsturz
 
Das Problem hatte ich auch...

Ich habe es gelöst, indem ich zuerst im Hauptthread eine boolean Variable eingeführt habe, welche beim Threadstart auf True gesetzt wird. Der Thread selbst setzt diese beim beenden über synchronize wieder auf false. Im Hauptthread habe ich eine boolean Variable "IsClosing", welche onClose auf True gesetzt wird. Der Hauptthread muss dann beim onClose (nachdem IsClosing auf true gesetzt wurde) nur noch warten bis der Thread nicht mehr läuft. Dafür kann man eine While schleife verwenden ;)

Riese 1. Dez 2005 09:36

Re: Thread und Indy - Programmabsturz
 
Hört sich gut an. Löst das Problem aber nicht.
Statt deiner Idee mit der Zusatzvariable könnte man ja auch einfach abfragen ob der Thread noch läuft, oder hab ich was falsch verstanden? (Wie das genau geht weiß ich grad net aber ich meine ich hätte es hier irgendwo gelesen?!)

der Thread hängt doch aber in der Methode ReadBuffer solange bis eine bestimmte Anzahl an Daten kommen. Kommen nun keine Daten, würde das System ja sich aufhängen in Deiner while Schleife, oder?

Gibt es keine SOFORT_THREAD_BEENDEN_METHODE?

Riese 2. Dez 2005 08:50

Re: Thread und Indy - Programmabsturz
 
Nachdem bisher nicht sooo viele Antworten kamen ;-) will ich die Anfrage mal in ein paar kleinere Fragen zerteilen.

Das wichtigste zuerst (der Rest später):
Hat jemand Erfahrungen mit der Indy TCPClient-Komponente und da vor allem mit dem Timeout beim Lesen einer Verbindung. Wie macht ihr das, wie gross ist die Timeout Zeit. Was passiert falls die Timeout-Exception ausgelöst wird.

Gruß
Riese

Der_Unwissende 2. Dez 2005 10:20

Re: Thread und Indy - Programmabsturz
 
Hi,
ich denke deine Fragen kann man nicht so wirklich pauschal beantworten. Sicherlich kommt es stark darauf an, was du für eine Anwendung (und Geduldsspanne) hast, wie große man die Time-Out Zeit wählt.
Wie man sich bei einer eintretenden Exception ist natürlich auch die Sache des Entwicklers. Du kannst versuchen den Kontakt wieder herzustellen, halt n mal oder du sagst dem Benutzer dass keine Verbidung hergestellt werden konnte (orientier dich einfach an dem was z.B. mail-clients oder Webbrowser machen).

Was dein Problem mit terminate angeht, so hast du doch die Schleife entworfen, die wartet, oder? Also du bekommst ja ein Ereignis wenn Daten ankommen und kannst dann mit den Daten irgendwas machen. Wenn ich dich richtig verstanden hab gehst du an der Stelle in eine Schleife und wartest bis xxx-Byte da sind. Dann musst du nur in dieser Schleife überprüfen ob terminated sich auf true geändert hat und ggf. die Schleife mittels break verlassen.

Gruß Der Unwissende

Riese 2. Dez 2005 12:27

Re: Thread und Indy - Programmabsturz
 
Danke "Unwissender".

Also ich werde es wohl so machen, dass ich ein Timeout auf ein paar Sekunden setze. Dann würde ja die Exception ausgelöst und dort prüfe ich dann ab, ob der Thread Terminated ist.
Dort kann ich doch mit einem "return" (bin ja innerhalb OnExecute des Threads) sofort den Thread beenden, oder?
Bisher habe ich keinen Timeout in ReadBuffer so dass der Thread nie beendet wird.

Gruß
Riese

Riese 2. Dez 2005 12:30

Re: Thread und Indy - Programmabsturz
 
Ach noch etwas was mich dazu auch brennend interessiert.
Mit Synchronize muss ich ja im Thread auf Komponenten der Form1 (u.a.) zugreifen.

Gilt das nur für die sichtbaren Eigenschaften oder zum Beispiel auch auf mein Indy-TCPClient der ja auch dort liegt.
Gibt das nur Probleme falls ich in Form1 auch darauf zugreifen würde (zum Beispiel TCPClient -Disconnect(!)) oder kann das immer zu Problemen führen bei der Ausführung des Programms?

Gruß
Riese

Der_Unwissende 2. Dez 2005 14:18

Re: Thread und Indy - Programmabsturz
 
Ja, was soll ich sagen, du stellst echt gute Fragen :mrgreen:

Wichtiger Grundsatz für gutes Nicht-Sequentielles Programmieren ist es, sperren so spät wie möglich setzen und so früh wie möglich entfernen. Dabei muss "wie möglich" auch wörtlich genommen werden.
Es ist gerade das Problem der Threads, dass du nicht sagen kannst ob es immer Probleme gibt oder nicht, kann die ersten 100000 mal gut gehen und beim nächsten nicht. Deshalb musst du es dir für dein (spezielles) Problem überlegen.

Du solltest immer dort synchronize einsetzen, wo es einen gleichzeitigen Zugriff geben kann und einer davon schreibend ist. Es ist unbendenklich beliebig viele Threads die selbe Variable lesen zu lassen, aber wenn einer ändert hast du ein Problem. Ganz wichtig ist es hier dann zu überlegen ab wo synchronized Sinn macht, beliebtes Beispiel: Zwei Threads A und B lesen x, erhöhen x um eins und schreiben es zurück. Nun sperrst du nur das Schreiben, dann kann es dazu kommen das A x liest, dann kommt b und liest x, beide erhöhen (in beliebiger Reihenfolge x), dann schreibt a x zurück (x = x+1) und jetzt kommt b ein weilchen nicht zum zug, A erhöht noch 10 mal x um 1 (x = x + 10) und nun kommt b wieder dran und nun ja, neun Erhöhungen gehen sofort verloren (b schreibt nur x+1 zurück).

Wie du hier vielleicht schon erahnen kannst, kann man schnell Dinge vergessen. Auf der sicheren Seite bist du, wenn du die ganze Methoden synchronzed setzt. Moment, merk gerade dass ich da was mit Java durcheinander bringe. Bei Delphi bekommst du ein Objekt (TCriticalSection) und musst so deine kritischen Stellen umschließen.

Um noch mal explizit auf deine Frage einzugehen, es ist egal was du änderst, es kann immer zu Problemen kommen wenn das gleichzeitig passieren könnte. Lesen kannst du hingegen aus beliebig vielen Threads gleichzeitig. Die Probleme die hier entstehen können haben nur was mit Fairness zu tun (wenn einer liest kann auch ein zweiter kommen und lesen, auch ein dritter, ... Kommt ein der schreiben will muss er warten, tja, wenn immer mehr lesende kommen wird halt nie geschrieben aber anderes Thema).
Ob eine Eigenschaft sichtbar ist oder nicht ist dabei vollkommen egal.
Wenn eine Komponente Thread-Safed ist, dann sollte ein setter dafür sorgen, dass nur ein Thread die Variable lesen bzw. schreiben kann. Ist eine Komponente nicht explizit als Thread-safed markiert, so kannst du nicht davon ausgehen dass es keine Probleme gibt.

Hoffe konnte helfen,

Gruß

Riese 2. Dez 2005 14:29

Re: Thread und Indy - Programmabsturz
 
Wow!

Super ausführlich! Danke !!!
Jetzt habe ich das mit Synchronize verstanden. Es kann also auch beim Trennen einer Verbindung knallen wenn ein anderer Thread gerade auf Bytes wartet.

Gruß aus dem schönen Süddeutschland

Riese


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:56 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