Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Timeout für sich aufhängenden Thread/Timeout allgemein (https://www.delphipraxis.net/131097-timeout-fuer-sich-aufhaengenden-thread-timeout-allgemein.html)

s.h.a.r.k 18. Mär 2009 20:41


Timeout für sich aufhängenden Thread/Timeout allgemein
 
guten abend,

ich hab mal wieder ein "problem" mit threads... oder generell gesagt mit timeouts.

wie ich auf das problem gekommen bin: ich nutze anydac 1.x und connecte zu einer datenbank. soweit, so gut... nur wenn der server nicht vorhanden ist (falschen server angegeben), so hängt sich das programm beim connecten auf, da sich anydac aufhängt.

nun gut, eigentlich doch einfach: die connectenmethode in einen thread auslagern, dann einen timeout drum herum programmieren und eine meldung an den user ausgeben, wenn es nicht geklappt hat. aber pustekuchen... :wall: denn entweder mache ich was falsch, oder das was ich will klappt so nicht.

ich habe das wie folgt (pseudocode):
Code:
initialisiereDaten;
starteThread;
while (not Timeout) and (not Answer) do
  warte
if Teimout then
  [b]TerminateThread(x)[b]
else
 allesOk
wie man im pseudocode sehen kann ist die verwendete methode, um den thread zu beenden, oder eher abschießen, die TerminateThread-methode. ob das aber die richtige ist, weiß ich nicht wirklich, da die hilfe etwas davor warnt. ich laufe dabei auch in das problem, dass der thread sich nicht wirklich beendet, da das programm sich danach nicht mehr schließen lässt. ich glaube, dass immer noch auf die beendigung gewartet wird.

meine frage ist nun: ist das eine richtige timeout-programmierung oder wie geht man sowas denn nun wirklich an?

bevor ihr nun daher kommt und mein, dass ich anydac ersetzen soll: nein, das geschieht nicht, da ich nicht die zeit dazu habe! das problem lässt sich ja auch darauf reduzieren, dass sich der thread aufhängt (endlosschleife oder sonst was).

ich hoffe, ihr könnte mir helfen!

mfg
armin

Pro_RJ 18. Mär 2009 21:46

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Guten Abend,
das Problem kenne ich nur zu gut.
Ich kenn mich zwar mit "anydac" nicht aus aber,
Ich habe eine Kommunikation, wo sich der Thread auch ab und zu "aufhängt" und ich habe auch keine wirkliche lösung gefunden. Mit "TerminateThread" setzt man ja nur eine interne Variable (Terminate := True).Nur über diese function kann man einen Thread nicht wiklich "Zwangsweise" beenden.Bei mir konnte ich das Problem nur so lösen, das ich den Thread in einen anderen Process ausgelagert habe und diese Prozess bei bedarf per TaskKill abgeschoßen habe. Aber das bringt ja in diesem Fall nichts, da du ja die DB-Verbingung in dem Prozess benötigst.

Was man aber eventuell versuchen könnte:
in einem extra Prozess versuchen ob man eine DB-Verbindung aufbauen kann
--> wenn dies gelingt dann im HauptProgramm die eigentliche Verbindung aufbauen
--> wenn es nicht gelingt dem Anwender eine Info geben.
Aber ich finde, das ist keine wirklich schöne Lösung aber sie funzt (ich sprech hier aus Erfahrung).

Dies ist vieleicht keine richtige hilfe aber eventuell ein Lösungsansatz.
mfg
Jens

quendolineDD 18. Mär 2009 21:51

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Du kannst doch auch ein Event starten, was beim erfolgreichen Verbinden zur Datenbank gesendet wird. Auf dieses Event warest du mit WaitForSingleObject(EventHandle, TIMOUT); Mit TIMOUT gibts du die Millisekunden an, die gewartet wird.

Luckie 18. Mär 2009 21:55

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von Pro_RJ
Bei mir konnte ich das Problem nur so lösen, das ich den Thread in einen anderen Process ausgelagert habe und diese Prozess bei bedarf per TaskKill abgeschoßen habe.

Warum denn das? Man kann einen Thread auch mit der API-Funktion MSDN-Library durchsuchenTerminateThread hart beenden, was aber möglichst vermieden werden sollte.

Ich würde übrigens mit MSDN-Library durchsuchenWaitForSingleObject auf den Thread warten bzw. mit MSDN-Library durchsuchenMsgWaitForMultipleObjects um noch auf Ereignisse reagieren zu können.

Pro_RJ 19. Mär 2009 06:48

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von Pro_RJ
Bei mir konnte ich das Problem nur so lösen, das ich den Thread in einen anderen Process ausgelagert habe und diese Prozess bei bedarf per TaskKill abgeschoßen habe.

Warum denn das? Man kann einen Thread auch mit der API-Funktion MSDN-Library durchsuchenTerminateThread hart beenden, was aber möglichst vermieden werden sollte.



Nun mit "TerminateThread"konnte ich in meinem Fall den Thread nicht beenden, deshalb habe ich den Thread ausgelagert.

s.h.a.r.k 19. Mär 2009 07:50

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
das problem ist doch, wie pro_rj schon richtig erkannt hat, dass sich der thread, auf den gewartet wird (egal in welcher art und weise), sich aufhängt, egal aus welchen gründen.

wie kann ich so einen thread auf normale art und weise beenden?

das habe ich schon getestet und das geht nicht:
- Thread.Free;
- FreeAndNil(Thread);
- Thread.Terminate();
- Thread.DoTerminate;
- TerminateThread(ThreadHandle, 0);

diese WaitFor...-methode bringt hier ja auch nichts, da der thread dadurch ja auch nicht zwangsweise beendet und dessen speicher wieder freigegeben wird.

wie könnte ich sonst noch an das problem heran gehen, außer den umweg über einen externen prozess?

Luckie 19. Mär 2009 08:02

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Was für eine Fehlermeldung bekommst du bei TerminateThread?

Pro_RJ 19. Mär 2009 08:21

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Das Problem ist, selbst wenn WaitFor irgendwann wieder zurück kommt hängt der Thread immernoch und man steht wieder vor dem gleichen Problem.

s.h.a.r.k 19. Mär 2009 09:07

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
wie pro_rj gesagt hat: keine fehlermeldung, lediglich ein stehen bleiben des programms. das einzige was dabei plausibel schien war den thread abschießen, also inkl code aus dem speicher entfernen, nur MSDN-Library durchsuchenTerminateThread() macht das leider nicht...

Pro_RJ 19. Mär 2009 09:41

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
TerminateThread() schickt ja auch nur an den Trhead ein signal alla "Schau mal das du in nächster Zeit Fertig wirst" das funst aber nur, wenn der QuellText des Threads Beendet ist. Da er aber nie Beendet wird läuft er immer weiter

s.h.a.r.k 19. Mär 2009 10:56

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
hm... das muss ich dann wohl leider überlesen haben :( aber es muss doch eine möglichkeit geben, so einen thread zu "zeigen wo es lang geht"!

Pro_RJ 19. Mär 2009 11:13

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Ja sowas habe ich mir auch gesagt, aber nach ner guten Woche suchen aus ausprobieren bin ich leider zu keinem wirklichen Ergebniss gekommen.
Ich denke auch das es irgendwie möglich sein muss einen Thread zu beenden, egal ob der nun will oder nicht.

mleyen 19. Mär 2009 11:15

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Netzstecker ziehen? Speicher nullen? :spin:

Liegt das Problem nicht eher am Quelltext im Thread?
In welcher Endlosschleife hängt er denn?

Pro_RJ 19. Mär 2009 11:22

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Das Problem ist nicht zwingend ein Programmfehler im eigenen Quelltext.
Bei mir z.B. bleibt ein Modem einfach stehen und meldet sich nicht mehr (gesteuert über Fremden Quelltext auf den ich keinen einfluss habe).

In diesem Beispiel tritt der "Fehler" ja beim Verbinden einer Datenbank auf.Ich stell mal die Theorie auf, das der Vorgang des Datenbankverbindens nicht von dir Programmiert wurde sondern das es über eine fertige Komponente läuft.(Korregier mich bitte wenn ich hier falsch liege).

PS: kennst du zufällig den Befehl für "Stecker auswerfen - Stecker wieder einstecken" :lol:

s.h.a.r.k 19. Mär 2009 13:24

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
*hehe* die ideen werden echt immer besser ;)

wie schon von pro_rj gesagt: der quelltext, er hängt ist nicht in meinen handlungsbereich. den quelltext habe ich nicht geschrieben und ich komme auch nicht dran. auch wenn ich es könnte, weiß ich nicht was ich da ändere. es geht auch allgemein um das prinzip dabei, wie ich finde. eni fehler in meiner bzw. in pro_rj's programmierung liegt nicht vor, das ist eine voraussetzung.

Reinhard Kern 19. Mär 2009 13:28

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von s.h.a.r.k
hm... das muss ich dann wohl leider überlesen haben :( aber es muss doch eine möglichkeit geben, so einen thread zu "zeigen wo es lang geht"!

Hallo,

das Problem haben andere Datenbanken auch, und es scheint auch eine Lösung zu geben, wenn man die Thread-ID bestimmt. Lies mal das hier:

http://www.builderau.com.au/architec...9130339,00.htm

Vielleicht hilft das weiter, jedenfalls scheint mir die Sache nicht hoffnungslos.

Gruss Reinhard

s.h.a.r.k 19. Mär 2009 22:08

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
danke für die idee, aber es liegt nicht an oracle! es liegt daran, dass der thread einfach stehen bleibt und sich aufhängt. dass da intern was mit einem verbindungsversuch zu einer oracle-db zu tun hat, ist eher zufall! trotzdem nochmals danke ;)

Luckie 19. Mär 2009 22:11

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von Pro_RJ
TerminateThread() schickt ja auch nur an den Trhead ein signal alla "Schau mal das du in nächster Zeit Fertig wirst"

Nein tut es nicht:
Zitat:

TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code.
Und deswegen wollte ich wissen, was GetLastError für einen Fehlercode zurückgibt.

Reinhard Kern 19. Mär 2009 23:17

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von s.h.a.r.k
danke für die idee, aber es liegt nicht an oracle!

Hallo,

natürlich nicht - tut mir ja leid, dass ich keinen fixfertigen Code liefern kann wie erwartet, meine Idee war nur, wenn der Schreiber von Orakill.exe in der Lage ist, mit der Thread-ID einen Thread zu killen, dann besteht offenbar diese Möglichkeit. Im Gegensatz dazu kommen die meisten Diskussionen, die ich zu dem Thema gesehen habe zu dem Ergebnis, dass es nicht geht oder zu garkeinem. Wie üblich findet man viele Fragen und wenig Antworten.

Deshalb glaube ich auch nicht, dass du etwas findest, was du nur kopieren oder downloaden musst.

Gruss Reinhard

alzaimar 20. Mär 2009 06:29

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Falls es gar keine saubere Lösung gibt, könntest Du vor dem Verbindungsversuch per anyDAC versuchen, den Server anzupingen. Wenn das klappt, versuche eine ADO- oder DBExpress-Verbindung aufzubauen. Wenn das klappt, verwende dein anyDAC.

Das löst das Problem zwar nicht, könnte aber trotzdem zum Ziel führen.

messie 20. Mär 2009 07:32

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Hast Du es denn jetzt mal geschafft, den Thread abzuschießen?

Denn Deine zuerst genannte Timeout-Routine sieht ja eigentlich logisch aus.
Ich habe TerminateThread noch nie verwendet, aber in einigen Routinen habe ich zur Absicherung Thread := nil.
Das ist zwar hässlich, geht aber.

Grüße, Messie

DasZiesel 20. Mär 2009 09:02

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von messie
Thread := nil.

Schaffst du dir damit nicht ein Speicherleck?

messie 20. Mär 2009 09:13

Re: Timeout für sich aufhängenden Thread/Timeout allgemein
 
Zitat:

Zitat von DasZiesel
Schaffst du dir damit nicht ein Speicherleck?

Wahrscheinlich gleich mehrere. Aber manchmal muss man den Kollateralschaden in Kauf nehmen. In meinen Anwendungen trat das alle paar Wochen mal ein, verursacht durch die damals noch sehr instabilen Treiber der ersten USB/RS232-Wandler. Da schießt Du den Thread einfach mal eben ab uns startest ihn neu...

Mit so einem Wandler kann man das auch reproduzieren: einfach so ein Ding anschließen, einen Thread starten, der von der COM-Schnittstelle etwas pollt. Nach ein paar Zyklen den USB-Stecker rausziehen, damit hängt der Thread, und zwar völlig.

Grüße, Messie


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