![]() |
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. :?: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:09 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