![]() |
Form reagiert nicht während idftp1.get trotz application.processmessages
Hallo
Meine Android App lädt Daten von einem FTP Server herunter.
Delphi-Quellcode:
for i4 := 0 to filelistFINAL.Count-1 do begin
if stop=false then begin progressbar1.value:=i4+1; try form2.idftp1.Get(filelistFINAL[i4], gethomepath+'/Temp/'+filelistFINAL[i4],true); except end; end; end; Auf FORM1 möchte ich nun dem Nutzer mit einem Button die Möglichkeit geben diese Download's abzubrechen. Leider ist aber Form1 während des Downloads komplett eingefroren, so das mein "Abbruch Code" gar nicht ausgeführt werden kann. Deshalb habe ich gedacht ich könnte zB in idftp on work
Delphi-Quellcode:
einfügen um die form1 ansprechbar zu halten. Leider bringt es kein Effekt / Form1 reagiert einfach nicht.
application.processmessages
Habe dann zum testen diverse stellen mit
Delphi-Quellcode:
versucht aber egal wo ich es hinn pflanze, form1 reagiert einafch nicht. (Versucht habe ich es zB in einem Timer, idftp OnWork, on Workbegin/end, in der Schlaufe des idftp.get Downloads)
application.processmessages
Weiss jemand wie ich form1 ansprechbar lassen kann? |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zieh dir mal eine
![]() |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
diese komponente gibt's eben für Android Anwendungen leider nicht.
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Schau mal hier:
![]() |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Hmmm. Also ich weiss nicht. Vermutlich mache ich es falsch :(
Habe mir das Beispiel einmal heruntergeladen und versucht es zu übernehmen. (Alles was ich nicht verstanden habe, habe ich einfach weggelassen :oops::oops: ) ![]() Aber ich glaube das so wie ich das gemacht habe, läuft alles genau "gleich ab". Nur das der Code oben in einer Procedure steht.
Delphi-Quellcode:
procedure geeTest(Source: string; dest: string);
begin try form2.idftp1.get(source, dest, true); sleep(400); application.ProcessMessages; except end; end;
Delphi-Quellcode:
for i4 := 0 to filelistFINAL.Count-1 do begin
if stop=false then begin progressbar1.value:=i4+1; try geetest(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4]); except end; end; end; |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Ich habe in einer meiner Apps den Aufruf von TIdHTTP in einen Thread ausgelagert. Damit funktioniert die Anzeige mit dem TAniIndicator hervorragend.
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Danke für eure Antworten.
Könnt ihr mir evt etwas helfen mit diesem Thread. Habe das bis jetzt noch nie gemacht. Also mit Google und DocWiki ![]() Habe ich in Delphi unter: Datei->NEU->Andere->Thread Object ein neues "Thread Formular erstellt" das heisst nun threadtest.pas Das Programm startet nun und ich versuche auf Form1 diesen "Thread Code" so aufzurufen:
Delphi-Quellcode:
Dann gibt es aber eine Exception Meldung (Access Violation at Adress 61B3D93C, accessing adress 00000000)
geetest.Create(False);
In diesem "Thread Formular" habe ich nun folgendes drinn: (Vermutlich ziemlich alles falsch :oops:)
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. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
[OT]Autsch[/OT]
Ich nehme zwar kein FTP, sondern http... Aber die Funktionalität ist ja fast die selbe...
Delphi-Quellcode:
Mavarik
Procedure Foo;
var URL, Dateiname : String; begin URL := 'Http://www.meinserver.de/Datei.png'; Dateiname := 'C:\Hierhin\Datei.png'; lThread := TAnonymousThread<boolean>.Create( function: boolean var idhttp : TidHttp; FS : TFileStream; DN : String; begin DN := Dateiname; result := true; if not(fileExists(DN)) then begin FS := TFileStream.Create(DN,fmCreate); try idhttp := Tidhttp.Create; try idhttp.Get(URL,FS); finally idhttp.Free; end; finally FS.Free; end; end; end, procedure(AResult: Boolean) begin end, procedure(AException: Exception) begin //Runs in main thread //ShowMessage(AException.Message); end); end; |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Also will mich jetzt wirklich nicht quer stellen. Aber wo hast du nun diesen Code drinn? In dem neuen Thread? oder auf der zB Form1? |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
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.
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
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:
Delphi-Quellcode:
Erhalte dann folgendes Fehler:(Access Violation at Adress 61B3D93C, accessing adress 00000000)
geetest.Create(False);
Aber ich habe bis jetzt noch nie mit Threads gearbeitet und verstehe es irgendwie noch nicht ganz wie das funktioniert / was ich falsch mache. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
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 :) |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Ich danke euch allen für eure Hilfe und Geduld.
Jetzt funktioniert es :-D |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
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:
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:
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.
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Delphi-Quellcode:
NICHT in deinem Thread aufrufen, weil du sonst die Funktion im Hauptthread der Anwendung aufrufst (
Form1.IdFtp1.Get()
Delphi-Quellcode:
) und diese dort auch ausgeführt wird. Das heisst dass dein Thread in dem Moment garkeinen Sinn mehr hat.
TForm1
Was du in etwa machen musst:
Delphi-Quellcode:
Aufruf in deiner
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.
Delphi-Quellcode:
Form1
Delphi-Quellcode:
Ungetestet und ausm Kopf. Also kopier das jetzt nicht einfach 1:1 und sag dann "Es geht nicht!!!111". Da krieg ich schlechte Laune. :mrgreen:
procedure TForm1.Button1Click(Sender: TObject);
begin TTestThread.Create(filelistFINAL); end; 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. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
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).
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
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:
Delphi-Quellcode:
habe
Form1.idftp1.get...
Delphi-Quellcode:
Funktioniert aber so gut, das ich mich kaum getraue was zu ändern :-D
form1.idftp1.get(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4], true);
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Nun dann solltest du beten, dass du die Form niemals umbenennst und den Thread nur einmal erzeugst ...
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Aber ich habe jetzt den Thread 3-4 mal im selben Programmstart aufgerufen und es klappt tiptop. :?: |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Bzw. zeig doch mal den Code, wie du den Thread "aufrufst" ... |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Das ist der "Thread"... Auf der Form? Das ist nix zum draufklicken... Nur aufrufen... Mavarik |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
@SirRufo
So ruf ich ihn auf (in einem Button)
Delphi-Quellcode:
Und das ist der komplette Thread :oops:
geetest.Create(False);
Delphi-Quellcode:
unit threadtest;
interface uses System.Classes, f1diashow,f4einstellungendiashow, System.SysUtils; type geetest = class(TThread) protected procedure Execute; override; end; implementation procedure vclsettings; begin form1.Image1.Visible:=true; form1.Image1.Bitmap.LoadFromFile(playlist[0]); form1.image1.Height:=form1.Height; form1.image1.Width:=form1.Width; form1.image1.Position.X:=0; form1.image1.Position.Y:=0; count:=0; form1.speedbutton1.Visible:=false; form1.speedbutton3.Visible:=false; form1.listbox1.Visible:=false; form1.Panel2.Visible:=false; form1.Timer1.Enabled:=true; form1.speedbutton2.Visible:=true; form1.label3.Visible:=false; form1.progressbar1.Value:=0; end; procedure geetest.Execute; var i4: integer; begin NameThreadForDebugging('threadgee'); { Place thread code here } if filelistFINAL.Count>form4.SpinBox2.Value-1 then form1.progressbar1.Max:=form4.SpinBox2.Value else form1.progressbar1.Max:= filelistFINAL.Count; for i4 := 0 to filelistFINAL.Count-1 do begin if stop=false then begin form1.progressbar1.value:=i4+1; try form1.idftp1.get(filelistFINAL[i4],gethomepath+'/Temp/'+filelistFINAL[i4], true); except end; PlayList.add(gethomepath+'/Temp/'+filelistFINAL[i4]); //Während des Downloads wird die DIASHOW gestartet (ja nach Puffer Grösse) if form1.Timer1.Enabled=false then begin if filelistfinal.Count>form4.SpinBox2.Value-1 then begin //SOFERN playlist grösser ist als der Puffer if PlayList.Count>form4.spinbox2.value-1 then begin form1.progressbar1.value:=i4+1; form1.timer1.interval:=strtoint(form4.SpinBox1.text)*1000; Synchronize(vclsettings); end; // ist die FileListFINAL kleiner als der Puffer und aber mindestens 1 Bild geladen end else if playlist.count>-1 then begin form1.progressbar1.value:=i4+1; form1.timer1.interval:=strtoint(form4.SpinBox1.text)*1000; Synchronize(vclsettings); end; end; end else begin //Schlaufe wir abgebrochen da Boolean STOP=TRUE ist form1.timer1.Enabled:=false; form1.image1.Bitmap:=nil; form1.speedbutton1.Visible:=true; form1.speedbutton3.Visible:=true; form1.listbox1.Visible:=true; form1.image1.Visible:=false; form1.label3.Visible:=true; form1.speedbutton2.Visible:=false; form1.panel2.Visible:=false; break; end; end; end; end. :oops: @ Mavarik: Ja habe eben bis heute noch nie mit einem Thread gearbeitet. (Wie du wahrscheinlich sehr gut am meinem oben erkennen kannst). :oops::oops: @nuclearping Irgendeinen Unterschied macht es schon. den so friert die form1 nicht mehr ein. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Ich weiß nicht wo ich da anfangen soll ... ok, da ist irgendwie alles falsch, was man falsch machen kann.
Die Funktion kommt glücklicherweise zustande und unglücklicherweise tut da tatsächlich was, so dass du denkst, so kann man das ruhig machen. Ein Tutorial zum Thema Threadding und Grundlagen zum Threadding allgemein wären dringend angebracht, wenn du ernsthaft mit Threads arbeiten möchtest. Das ist allerdings der Ritt auf Messers Schneide ohne Gurt. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
ok. Muss mich da mal komplett informieren. Bis heute bin ich immer ohne Threads ausgekommen.
Danke |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Zitat:
Das ich die Erzeugung von IdFtp1 im Thread für besser halte, lassen wir mal außen vor... Das es ggf. Probleme geben kann, falls Form1 schon weg ist auch... Funktionieren würde es trotzdem! Mavarik |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Da stand einer noch nie im Stau!...:lol: |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Zitat:
Oder meinst du etwa nicht fahren dürfen bzw. nicht fahren sollen? |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
[OT]Einfach den Standstreifen nehmen...[/OT]
|
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Es gab mal eine Werbung irgendeines Autoherstellers. Der wollte vermutlich darstellen wie gut man mit dieser übergroßen Karre durch den Stadtverkehr kommt. Jedefalls war die Kreuzung in der Quere dicht und da tauchte das Auto in die Staße ein, so als sei sie aus Wasser und kam auf der anderen Seite wieder hoch.
![]() So kommt man bestimmt auch ganz gut unter einem Stau vorbei. In Delphi wähe das dann so ähnlich, als wenn man alle Schutzmaßnahmen umgeht und von hinten durch die Brust die Oberfläche aktualisiert. |
AW: Form reagiert nicht während idftp1.get trotz application.processmessages
Ich wollte eigentlich darauf hinaus, das der Thread (das Auto) unabhängig von allen anderen Dingen lauffähig sein sollte um tatsächlich sinnvoll benutzbar zu sein. Wäre ja echt dämlich, wenn ich mir mit meinem Nachbarn den Motor teilen müsste (engine-sharing). Den gleichen Motor ok, aber eben nicht den selben.
Alles andere sind Regeln an die man sich halten sollte, weil es sonst kracht oder eben schlechter funktioniert:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz