Toon posts:

[Delphi] 'vastloper' detecteren

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben bezig met een applicatie waarbij ik om de zoveel tijd een aantal LOG-files van een FTP server moet binnen halen, tonen en analyseren.

De applicatie bestaat uit drie afzonderlijke threads: Ééntje die om de zoveel tijd met de FTP server verbindt om de LOGs op te halen (de replicatie thread). Ééntje die, op basis van een lijst van opgehaalde logs, deze analyseert. En ééntje (de form-thread) waarin de logs te bekijken zijn en de analyse resultaten getoond worden. Dit werkt allemaal zolang alles goed gaat.

Echter, wanneer de FTP server waar de LOGs van opgehaald worden om de één of andere reden de connectie met mijn applicatie verliest TIJDENS een file transfer loopt de hele replicatie thread vast. Heeft iemand enig idee hoe ik dit kan detecteren en op kan lossen? Ik heb al geprobeerd een timer voor de FTP GET functie te starten, maar wanneer de GET vastloopt wordt ook de OnTimer procedure niet aangeroepen.

Iemand enig idee hoe ik dit op kan lossen??

BTW: ik werk met Delphi7 icm Indy9 (TIdFtp component).

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 08-05 18:37

Tomatoman

Fulltime prutser

Je kunt hiervoor een synchronisatie-object zoals een mutex in combinatie met WaitForSingleObject gebruiken. Lees [rml][Delphi] Threads en locken[/rml] eens door.

[ Voor 9% gewijzigd door Tomatoman op 25-03-2005 15:31 ]

Een goede grap mag vrienden kosten.


Verwijderd

Topicstarter
tomatoman schreef op vrijdag 25 maart 2005 @ 15:27:
Je kunt hiervoor een synchronisatie-object zoals een mutex in combinatie met WaitForSingleObject gebruiken. Lees [rml][Delphi] Threads en locken[/rml] eens door.
Maar in dat geval kijk je naar de status van de gehele thread?? Ik wil eigenlijk uitsluitend naar een enkele functie kijken. De replicatie thread, waar de FTP GET onderdeel van is, is redelijk groot.

Ik heb overwogen een aparte GET thread te maken, maar in sommige gevallen moeten er wel 1000 logs opgehaald worden, dan zou er ook 1000 keer ingelogd moeten worden (iedere keer dat de GET thread draait). Of is het mogelijk vanuit de éne thread gebruik te maken van de ftp connectie in de ander? Nee toch?

[ Voor 33% gewijzigd door Verwijderd op 25-03-2005 15:52 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 08-05 18:37

Tomatoman

Fulltime prutser

Verwijderd schreef op vrijdag 25 maart 2005 @ 15:38:
[...]

Maar in dat geval kijk je naar de status van de gehele thread?? Ik wil eigenlijk uitsluitend naar een enkele functie kijken. De replicatie thread, waar de FTP GET onderdeel van is, is redelijk groot.

Ik heb overwogen een aparte GET thread te maken, maar in sommige gevallen moeten er wel 1000 logs opgehaald worden, dan zou er ook 1000 keer ingelogd moeten worden (iedere keer dat de GET thread draait). Of is het mogelijk vanuit de éne thread gebruik te maken van de ftp connectie in de ander? Nee toch?
Bij het creëren van de replicatiethread creëer je een mutex, die je pas weer releaset in de destructor van de thread. Bovendien maak je dan een controlethread in suspended state. Telkens wanneer de replicatiethread een FTP Get uitvoert, doe je het volgende:
  1. Maak de mutex nonsignaled, zodat WaitForSingleObject zal wachten totdat de mutex weer signaled is.
  2. Resume the controlethread.
  3. Voer het FTP GET commando uit.
  4. Maak de mutex weer signaled.
Zodra de replicatiethread wordt vernietigd, vernietigt hij de controlethread met Controlethread.Terminated := True en Controlethread.Resume.

De controlethread moet het volgende doen:
Delphi:
1
2
3
4
5
6
7
8
9
while not Terminated do
begin
  if WaitForSingleObject([de mutex], [maximale wachttijd]) = WAIT_TIMEOUT then
    // GET is vastgelopen
  else
    // GET is netjes uitgevoerd of mutex is released
  if not Terminated then
    Suspend; // thread is klaar voor de volgende Resume
end;

Per replicatiethread heb je precies één controlethread nodig. De replicatiethread kan een willekeurig aantal GET's uitvoeren. Wil je meer GET's tegelijk doen, dan heb je meerdere replicatiethreads nodig.

[ Voor 22% gewijzigd door Tomatoman op 25-03-2005 16:41 ]

Een goede grap mag vrienden kosten.


Verwijderd

Topicstarter
Ok, hij wordt me duidelijk... Ga ik mee aan de gang. Dank je!!

Verwijderd

Topicstarter
Nog één puntje, hoe kap ik een vastgelopen thread af?? Ja, een Terminate natuurlijk, maar dan ga je ervanuit dat de thread nog enige activiteit vertoond en een if-clause oid daarvoor bevat. Mijn huidige replicatie thread heeft een do-while lus die net zolang loopt als not terminated. Dit werkt goed, maar niet bij een vastloper. Free wil ook niet. De main tread loopt dan vast, maar de replicatie thread loopt rustig zijn programma af (ook niet wenselijk bij een vastloper, want hij loopt niet meer, DUUUH). Destroy heeft hetzelfde resultaat als Free.

Nu kan ik dan wel een vastloper detecteren, ik kan 'm alleen niet afsluiten en opnieuw starten. Iemand enige ideëen?

[ Voor 15% gewijzigd door Verwijderd op 01-04-2005 13:39 ]


Verwijderd

Verwijderd schreef op vrijdag 01 april 2005 @ 12:44:
Nog één puntje, hoe kap ik een vastgelopen thread af?? Ja, een Terminate natuurlijk, maar dan ga je ervanuit dat de thread nog enige activiteit vertoond en een if-clause oid daarvoor bevat. Mijn huidige replicatie thread heeft een do-while lus die net zolang loopt als not terminated. Dit werkt goed, maar niet bij een vastloper. Free wil ook niet. De main tread loopt dan vast, maar de replicatie thread loopt rustig zijn programma af (ook niet wenselijk bij een vastloper, want hij loopt niet meer, DUUUH). Destroy heeft hetzelfde resultaat als Free.

Nu kan ik dan wel een vastloper detecteren, ik kan 'm alleen niet afsluiten en opnieuw starten. Iemand enige ideëen?
Met TThread.destroy kom je er niet, zie de documentatie van TThread:
Destroy signals the thread to terminate and then waits for the thread to return before calling the inherited Destroy method.
Je kan TThread naar TObject casten en dan free-en, maar ik sta niet voor de gevolgen daarvan in :+ .

De handigste aanpak lijkt me zoals je zelf aandroeg, de GET methode slimmer te maken: stop met GETten als de connectie dropt.
Als je pre-emptive wil gaan multitasken zal je een thread-class moeten maken die dit ondersteunt.

Verwijderd

Topicstarter
Verwijderd schreef op vrijdag 01 april 2005 @ 14:25:
[...]
De handigste aanpak lijkt me zoals je zelf aandroeg, de GET methode slimmer te maken: stop met GETten als de connectie dropt.
Als je pre-emptive wil gaan multitasken zal je een thread-class moeten maken die dit ondersteunt.
Helaas is de GET functie een functie van een Indy component. Ik wil daar niet teveel aan rotzooien. Ik kan 'm wel aanroepen in weer een eigen thread, maar ook die moet ik kunnen slopen op het moment dat die vast loopt.

Overigens ben ik ondertussen overgestapt naar Indy 10 die transfer timeouts ondersteund. Scheelt een boel, maar af en toe loopt de thread nog steeds vast tijdens een GET.
Pagina: 1