AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Cross-Platform-Entwicklung Form reagiert nicht während idftp1.get trotz application.processmessages
Thema durchsuchen
Ansicht
Themen-Optionen

Form reagiert nicht während idftp1.get trotz application.processmessages

Ein Thema von gee21 · begonnen am 12. Jul 2014 · letzter Beitrag vom 15. Jul 2014
Antwort Antwort
Seite 2 von 4     12 34      
gee21

Registriert seit: 3. Jan 2013
199 Beiträge
 
Delphi 10.4 Sydney
 
#11

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 13:45
Nur kurz zur Erklärung, damit beim nächsten mal nicht wieder gefragt wird. Die Methode Get kehrt erst zurück, wenn sie fertig ist. Da kannst da du vor und danach so oft die Messageque abarbeiten wie du willst, die Methode wird dir trotzdem dein Programm blockieren. Wenn dann müsste das Apploication.ProcessMessages in die Get Methode rein. Da du aber da keinen Einfluss drauf hast, hilft es nur die Methode in einen separaten Thread auszulagern.

Vielen Dank für die Info.
Ich versuche ja den idftp1.get Befehl in einen Thread auszulagern. aber ich mache noch was falsch und weiss nicht genau was.

Thread:
Delphi-Quellcode:
unit threadtest;

interface

uses
     System.Classes, f1diashow, System.SysUtils;

type
   geetest = class(TThread)
   protected
     procedure Execute; override;
   end;


implementation


procedure geetest.Execute;
begin
   NameThreadForDebugging('threadgee');
   { Place thread code here }

   form1.idftp1.get(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4], true);
end;

end.

Versuche den Thread auf Form1 so zu starten:
 geetest.Create(False); Erhalte dann folgendes FehlerAccess Violation at Adress 61B3D93C, accessing adress 00000000)


Aber ich habe bis jetzt noch nie mit Threads gearbeitet und verstehe es irgendwie noch nicht ganz wie das funktioniert / was ich falsch mache.
Robert
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#12

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 14:28
Wenn du einen Thread baust, dann musst du den so bauen, dass der komplett autark laufen kann.
Wenn ein Thread autark ist, dann kann man diesen Thread auch n-fach parallel laufen lassen, ohne dass es zu Störungen kommt.

Ein Beispiel aus dem Leben:

Jedes Auto ist ein eigener Thread und jedes Auto kann völlig unabhängig voneinander fahren.

Wenn ich deine Umsetzung jetzt mal auf die Autos übertrage, dann hast du einen Motor (TIdFTP) und alle Autos benutzen diesen Motor. Irgendwie uncool
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
gee21

Registriert seit: 3. Jan 2013
199 Beiträge
 
Delphi 10.4 Sydney
 
#13

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 15:14
Ich danke euch allen für eure Hilfe und Geduld.

Jetzt funktioniert es
Robert
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#14

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 15:20
Generell empfiehlt es sich bei der Programmierung immer zu überlegen, wie das im realen Leben funktionieren würde.

Statt eine Datei per FTP zu laden stellen wir uns vor, wir wollen etwas besorgt haben. Eine Gurke (Datei) aus dem Supermarkt (FTP-Server). Da wir selber (GUI) gerade am telefonieren sind (Interaktion mit dem User) und den Teilnehmer nicht mit Geräuschlosigkeit verunsichern wollen (Anwendung reagiert nicht) schicken wir jemand Anderen (Thread) los.

Dieser Andere (Thread) braucht nun bevor er losgeht alle notwendigen Informationen um die Aufgabe zu erledigen:
  • Was soll besorgt werden? Eine Gurke (Datei foo.txt)
  • Wo soll das besorgt werden? Supermarkt gleich um die Ecke (ftp.foo.com)
  • Womit soll er kaufen? Mit Geld (Benutzername, Kennwort)
Diese Informationen schreibe ich ihm auf einen Zettel und gebe ihm den Zettel mit (man beachte, dass dieser Zettel nun ausserhalb des eigenen Zugriffs ist).

Irgendwann kommt derjenige dann wieder und hat, wenn nichts schief gelaufen ist, die Gurke (Datei) dabei.

Ab jetzt kann ich auf die Gurke (Datei) zugreifen.

Läuft etwas schief, dann kann ich auf die Gurke (Datei) natürlich nicht zugreifen:
  • Geld hat nicht ausgereicht (Zugangsdaten falsch)
  • Gurken waren aus (Datei nicht gefunden)
  • Der Supermarkt ist zur Zeit geschlossen (Server nicht gefunden)
  • ...

Weitere Betrachtungen:

Wenn ich über den aktuellen Zustand informiert werden möchte, dann muss der Andere (Thread) mich eben fortlaufend anrufen und mich informieren. Da ich aber am telefonieren und nicht unhöflich bin, nehme ich diesen Anruf nicht mitten im Satz an, sondern entschuldige mich kurz, nehme den Anruf und damit die Information an, und lege wieder auf (Synchronize).

Wenn ich schon sehr modern bin, dann lasse ich mir einfach eine SMS schicken und schaue mir wenn ich Zeit habe die Information an (Queue).

Meinen Gegenüber kann ich dann immer wieder über den Fortschritt unterrichten (Progressbar aktualisieren).

Abbruch des Auftrags:

Um den Auftrag abzubrechen, schicke ich dem Anderen (Thread) eine SMS (Event), dass ich die Gurke (Datei) nicht mehr benötige.
  • Ist er noch auf dem Weg dorthin, kehrt er einfach wieder zurück (vor der FTP-Verbindung)
  • Ist er schon im Supermarkt (Verbindung zum FTP-Server hergestellt, Datei wird geladen), dann einfach alles wieder weglegen und zurückkehren (Verbindung trennen und die bis jetzt geladenen Daten verwerfen)
  • Hat er die Gurke schon gekauft, dann die Gurke wegwerfen (Datei wieder löschen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#15

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 15:27
Delphi-Quellcode:
procedure geetest.Execute;
begin
   NameThreadForDebugging('threadgee');
   { Place thread code here }

   form1.idftp1.get(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4], true);
end;
Du darfst Form1.IdFtp1.Get() NICHT in deinem Thread aufrufen, weil du sonst die Funktion im Hauptthread der Anwendung aufrufst (TForm1 ) und diese dort auch ausgeführt wird. Das heisst dass dein Thread in dem Moment garkeinen Sinn mehr hat.

Was du in etwa machen musst:
Delphi-Quellcode:
unit threadtest;

interface

uses
  System.Classes, System.SysUtils,

  // Indy Units
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdExplicitTLSClientServerBase, IdFTP;

type
   TThreadTest = class(TThread)
     constructor Create(AFileListFinal: TStringList);
     destructor Destroy; override;
   protected
     FIdFtp: TIdFTP;
     FConnected: Boolean;
     FDownloading: Boolean;
     FFileList: TStringList;
     procedure Execute; override;

     procedure AfterGet(Sender: TObject; Stream: TStream);
     procedure Connected(Sender: TObject);
   public
   end;

implementation

function GetHomePath: String;
begin
  // Die Funktion darf ebenso KEINEN Zugriff auf Komponenten von Form1 oder sowas nehmen.
  Result := '/var/www/...';
end;

procedure TThreadTest.Execute;
var
  i4: Integer;
begin
   NameThreadForDebugging('threadgee');

   FConnected := FALSE;
   FDownloading := FALSE;
   i4 := 4;
   FIdFtp.Connect;

   while not Terminated do
     begin
       Sleep(1);
       if not FConnected then
         Continue;

       if not FDownloading then
         begin
           FDownloading := TRUE;
           Sleep(500);

           FIdFtp.Get(FFileList[i4], GetHomePath + '/Temp/' + FFileList[i4], TRUE);
         end;
     end;
end;

constructor TThreadTest.Create(AFileListFinal: TStringList);
begin
  FFileList := AFileListFinal;
  FIdFtp := TIdFTP.Create(nil);
  with FIdFtp do
    begin
      Host := '...';
      Username := 'lieschen';
      Password := 'purzel123';
      OnConnected := Connected;
      OnAfterGet := AfterGet;
    end;

  inherited Create(FALSE);
  FreeOnTerminate := TRUE;
end;

destructor TThreadTest.Destroy;
begin
  FIdFtp.Free;
end;

procedure TThreadTest.Connected(Sender: TObject);
begin
  FConnected := TRUE;
end;

procedure TThreadTest.AfterGet(Sender: TObject; Stream: TStream);
begin
  Sleep(500);
  FIdFtp.Disconnect;
  FConnected := FALSE;

  Terminate;
end;

end.
Aufruf in deiner Form1
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  TTestThread.Create(filelistFINAL);
end;
Ungetestet und ausm Kopf. Also kopier das jetzt nicht einfach 1:1 und sag dann "Es geht nicht!!!111". Da krieg ich schlechte Laune.

Es soll nur das Prinzip verdeutlichen. Das ist ungefähr das, was Sir Rufo mit "autark" meint. Dein Thread darf sich nicht (ohne weiteres) von Inhalten aus Form1 bedienen oder Funktionen darauf aufrufen.

Geändert von nuclearping (13. Jul 2014 um 16:31 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#16

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 15:52
Blöde Frage: Es ist korrekt, die FTP-Komponente im Hauptthread zu erzeugen (im Konstruktor), das 'Get' aber im Kontext des Threads aufzurufen? Ich würde die Komponente als lokale Variable im Execute erzeugen, verwenden und wieder freigeben (mit Try-Finally natürlich).
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#17

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 16:28
Blöde Frage: Es ist korrekt, die FTP-Komponente im Hauptthread zu erzeugen (im Konstruktor), das 'Get' aber im Kontext des Threads aufzurufen?
Das macht er ja. Und es funktioniert nicht.
  Mit Zitat antworten Zitat
gee21

Registriert seit: 3. Jan 2013
199 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 18:19
Hey Leute ihr seit super.

Ich glaube bei mir hat es zuerst nicht geklappt da ich nur die "idftp1.get" Zeile im Thread hatte und jetzt wo ich die ganze Schlaufe in den Thread genommen habe, läuft es perfekt und sehr sehr schnell.


Obwohl ich im Moment im Thread immer noch: Form1.idftp1.get... habe

form1.idftp1.get(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4], true); Funktioniert aber so gut, das ich mich kaum getraue was zu ändern
Robert
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#19

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 18:32
Nun dann solltest du beten, dass du die Form niemals umbenennst und den Thread nur einmal erzeugst ...
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
gee21

Registriert seit: 3. Jan 2013
199 Beiträge
 
Delphi 10.4 Sydney
 
#20

AW: Form reagiert nicht während idftp1.get trotz application.processmessages

  Alt 13. Jul 2014, 18:42
Nun dann solltest du beten, dass du die Form niemals umbenennst und den Thread nur einmal erzeugst ...
Ok, vielleicht ändere ich es dann doch noch lieber. Danke

Aber ich habe jetzt den Thread 3-4 mal im selben Programmstart aufgerufen und es klappt tiptop.
Robert
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 4     12 34      


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 12:49 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