AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Probleme mit Indy FTP in eigenem Thread

Ein Thema von karma · begonnen am 20. Feb 2009 · letzter Beitrag vom 21. Feb 2009
Antwort Antwort
karma

Registriert seit: 14. Mai 2008
27 Beiträge
 
#1

Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 19:42
Hallo Leute,
ich hoffe ich bin im richtigen Forum für meine Frage.
Ich habe folgendes Problem: Ich habe in meinem Programm den FTP Client in einen eigenen Thread ausgelagert, damit mein Form nicht hängt während er aktiv ist. Das funktioniert auch prima, allerdings wartet das Programm, wenn ich es beenden möchte, darauf, dass z.B. eine laufende Dateiübertragung fertiggestellt ist. Ich möchte aber, dass beim beenden eventuell laufende Übertragungen abgebrochen werden und sich das Programm sofort beendet.


Außerdem noch zwei andere Dinge: Im Programm gibt es einen Button, der den Download startet. Nach Fertigstellung soll dann ein Windows-Explorerfenster mit dem Download geöffnet. Ich habe das jetzt mit einer Schleife gemacht, die folgendermaßen aussieht:

 while(not ftpload.terminated) do application.ProcessMessages; Danach kommt dann der Aufruf zum Öffnen des Explorers. Vielleicht als kurzen Hinweis dazu, der Thread zerstört sich nicht selbst, und die boolvariable terminated setze ich im OnTerminate des Threads. Das funktioniert an sich, unschönerweise bewirkt die Schleife aber eine 100% CPU Auslastung. Ich dachte immer, Windows blockiert den Messageloop immer automatisch, damit das nicht passiert?
Ich kann den Explorer-Aufruf leider nicht aus dem Thread machen, weil ich zusätzlich dazu nach dem Download auch noch einen Eintrag in eine Datenbank machen muss. Und ich weiß nicht, ob ich auf eine ZEOS-Connection aus 2 Threads gleichzeitig zugreifen darf.


Zweites Problem ist, man könnte jetzt ja theoretisch ein weiteres Mal auf den Button klicken. Wenn der Thread jetzt noch läuft, soll ein Hinweis kommen, in dem man auswählen kann ob man den Thread beenden möchte, oder ob er weiterlaufen soll. Dazu ist ein MessageDlg drin, der beim Klicken auf Ja die terminate-Prozedur meiner TThread-Klasse aufruft. Leider beendet das aber den Thread nicht x) Ich schätze, hier ist das das gleiche Problem wie wenn man das gesamte Programm beenden möchte. Indy scheint den Thread so zu blockieren, dass er auf nichts anderes mehr reagiert.

Wie kann ich das Problem lösen? Vielen Dank für eure Hilfe!
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#2

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 20:47
Du hast doch im Thread die IdFTP-Klasse. Prüfe im OnWork of Terminated wahr ist. Wenn dem so ist, solltest du den Download beenden.

Damit kannst du den Thread per ftpload.Terminate; beenden.

Zitat:
Ich kann den Explorer-Aufruf leider nicht aus dem Thread machen,
Wenn du etwas machen möchtest, wenn der Thread beendet wurde brauchst du nicht ständig Application.Processmessages aufrufen (womit du, nebenbei bemerkt, das "warten auf neue Nachrichten" ad absurdum führst, da es nichts anderes ist als Polling)
sondern es müsste ein TThread.Terminated Event geben, in welchem du so etwas machen kannst. Alternativ eine synchronized-Prozedur
  Mit Zitat antworten Zitat
karma

Registriert seit: 14. Mai 2008
27 Beiträge
 
#3

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 22:07
Vielen Dank für deine Antwort. Stimmt, an OnWork habe ich gar nicht gedacht
Kann man eigentlich TThread auch vom Hauptthread killen lassen?

Zitat von jfheins:
Wenn du etwas machen möchtest, wenn der Thread beendet wurde brauchst du nicht ständig Application.Processmessages aufrufen (womit du, nebenbei bemerkt, das "warten auf neue Nachrichten" ad absurdum führst, da es nichts anderes ist als Polling)
sondern es müsste ein TThread.Terminated Event geben, in welchem du so etwas machen kannst. Alternativ eine synchronized-Prozedur
Ok, dann hab ich das wohl falsch verstanden, ich dachte OnTerminate wird noch aus dem Thread raus aufgerufen.


Zu dem Processmessages hab ich dann aber nochmal ne Frage Ich hatte mir das bis jetzt so vorgestellt, dass ich damit in den Messageloop komme und damit dann weiter Eingaben verarbeiten kann. Wie macht man es denn "richtig", dass, wenn ich jetzt folgendes Beispiel habe:

Ich habe einen Thread, in dem in einer bestimmten Zeit ein Zähler hochgezählt wird. Jetzt möchte ich in meinem Hauptthread eine Abfrage machen, ob der Zähler über einem bestimmten Wert ist und dann an der Stelle weitermachen. Die einzige Lösung die mir da einfällt ist in einer while Schleife immer wieder das Ergebnis zu überprüfen und processmessages aufzurufen, damit das Formular noch reagiert?
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#4

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 22:14
Zu der letzten Frage: Du kannst im Thread hochzählen, und gucken ob der Wert erreicht ist. Wenn das der Fall ist, rufst du ein Event im Hauptthread auf, in dem das ausgeführt wird, was passieren soll.

Um eine Methode im MainThread auszuführen musst du synchronize() verwenden.

Also z.B.
Delphi-Quellcode:
TMyThread = class(TThread)
i : Integer;
MainForm: TForm1;
// ...

procedure TMyThread.Execute()
begin
while i <= 1000
begin
inc(i)
sleep(50)
if i = 400 then
  synchronize(Ausgabe);
end;
end;

procedure TMyThread.Ausgabe()
begin
MainForm.Label1.Caption := inttostr(i);
// oder
MainForm.DoSomething(i);
// oder
Mainform.DoSomething(Self);
end;
  Mit Zitat antworten Zitat
karma

Registriert seit: 14. Mai 2008
27 Beiträge
 
#5

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 22:46
Zitat von jfheins:
Zu der letzten Frage: Du kannst im Thread hochzählen, und gucken ob der Wert erreicht ist. Wenn das der Fall ist, rufst du ein Event im Hauptthread auf, in dem das ausgeführt wird, was passieren soll.

Um eine Methode im MainThread auszuführen musst du synchronize() verwenden.
Ah, das ist natürlich gut zu wissen.
Meine Frage ist wohl doch etwas komplizierter, konkret handelt es sich bei dem Programm was ich meine um ein Projekt für die Uni, bei dem es um eine Robotersteuerung geht. Der Roboter wird über eine DLL gesteuert, die nur rudimentäre Befehle zum Bewegen und zur Positionsabfrage mitbringt. Über ein Skriptsystem kann man einen Bewegungsablauf für den Roboter festlegen.
Folgendes Problem: Die Befehle zur Bewegung kehren sofort zum System zurück. Ich will aber, dass der Roboter seine Bewegung erst abschließt und erst anschließend den nächsten ausführt. Bis jetzt habe ich das wie hier hingewurschtelt, und zwar mit einer Schleife, die mit while(RoboterInBewegung) abwartet und währenddessen application.processmessages aufruft, damit das Formular noch reagiert. Wie stelle ich es denn in diesem Fall am geschicktesten an? Die DLL stellt leider keinerlei Callbacks bereit, sodass ich nur abfragen kann, ob sich der Roboter bewegt oder steht. Außerdem soll der Roboter zwischen den einzelnen Bewegungen möglichst nicht stehen, deswegen geht auch kein sleep(50) oder etwas in der Art um die CPU zu schonen. Vielleicht hast du da ja noch eine Idee?

Vielen Dank auf jedenfall für deine Hilfe!
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#6

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 20. Feb 2009, 23:50
Also wenn die DLL nichts in der Richtung bereitstellt, isses natürlich doof.

In diesem Fall würde ich einen Thread benutzen, der die Robotersteuerung übernimmt.

Der kann dann ja z.B. eine Liste haben und wie folgt arbeiten:
Delphi-Quellcode:
procedure TThread.Execute;
begin
  while (not Terminated) and (not CommandQueue.IsEmpty) do
  begin
    Execute(CommandQueue.Pop());
    while Robot.ismoving do Sleep(0);
    // evtl. dem Mainthread den Fortschritt mitteilen
  end;
end;
Das Sleep(0) bewirkt hier, dass die Bearbeitung des Threads unterbrochen wird und andere Prozesse Rechenzeit bekommen (solange du ihn nicht auf Echtzeitpriorität stellst ...)

Das Ausgelagere in den Thread heißt, dass du auf Application.Processmessages verzichten kannst
  Mit Zitat antworten Zitat
karma

Registriert seit: 14. Mai 2008
27 Beiträge
 
#7

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 21. Feb 2009, 12:23
In der Doku ist leider noch angegeben, dass die DLL nicht Threadsafe ist. Vielleicht mach ich nochmal einen extra Thema zu der Frage auf wenn ich da weiter dran arbeite.

Dir auf jedenfall vielen Dank für eine ausfürliche Hilfe
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#8

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 21. Feb 2009, 13:35
Nicht-Threadsafe heißt, dass du die Funktionen nicht aus 2 verschiedenen Threads ausführen darfst.

Wenn du aber konsequent sämtliche Aufrufe in dem einen Thread machst (also im Hauptthread nichts dergleichen) dann sollte es keine Probleme geben

Es ist im Grunde egal wieviele Threads deine Anwendung hat, wenn die dll nicht thread-safe ist, bedeutet das nur dass höchstens ein Thread auf die DLL zugreifen darf. Welcher das ist darfst du dir aussuchen.
  Mit Zitat antworten Zitat
karma

Registriert seit: 14. Mai 2008
27 Beiträge
 
#9

Re: Probleme mit Indy FTP in eigenem Thread

  Alt 21. Feb 2009, 15:54
Jo, soviel war mir klar. Leider ist nur im Hauptthread schon ne ganze Menge Code, sodass der Umbau ziemlich aufwändig wäre. Naja muss ich mich vielleicht mal ran machen x)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:06 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