Autor Beitrag
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 14.01.06 19:11 
hi, ich habe in meinem programm einen kleinen ftp uploader, wenn dieser jedoch aktiv ist, hängt das ganz programm, also wollte ich das ganze in einen thread auslagern:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
procedure UploadPerFTP(Directory, sub: string);
  procedure GetDir(dir: string);
  var
    SearchRec: TSearchRec;
  begin
    Application.ProcessMessages;
    if ilch_stop then
      exit;
    if FindFirst(dir + '*.*', faAnyFile, SearchRec) = 0 then
    begin
      repeat
        if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
        begin
          if (SearchRec.Attr and faDirectory) = faDirectory then
          begin
            ilch_CreateFTPFolder(SearchRec.Name);
            MainForm.IdFTP.ChangeDir(SearchRec.Name);
            GetDir(dir + SearchRec.Name + '\');
            MainForm.IdFTP.ChangeDirUp;
          end
          else 
          begin
            MainForm.L_File.Caption := 'Datei: ' + SearchRec.Name;
            MainForm.IdFTP.Put(dir + SearchRec.Name, SearchRec.Name);
            Application.ProcessMessages; 
          end;
        end;
      until FindNext(SearchRec) <> 0;
      FindClose(SearchRec);
    end;
  end;
var
  dir: string;
  tid: cardinal;
begin
  dir := subpath;
  if dir <> '' then
  begin
    while Pos('/', dir) > 0 do
    begin
      Ilch_CreateFTPFolder(Copy(dir, 1, Pos('/', dir) - 1));
      MainForm.idFTP.ChangeDir(Copy(dir, 1, Pos('/', dir) - 1));
      Delete(dir, 1, Pos('/', dir));
    end;
  end;
  dir := directory;
  if dir[Length(dir)] <> '\' then dir := dir + '\';
  BeginThread(nil, 0, @getdir, pointer(dir), 0, tid);
  //if thread fertig ?
end;

beim ausführen bekomme ich haufenweise fehler, ich denke, das liegt daran, dass die arbeit fortgesetzt wird, ohne dass darauf gewartet wird, dass der thread mit seiner arbeit fertig ist (danach wird mit den hochgeladenen dateien gearbeitet), also muss ich irgendwie an der markierten stelle abfragen, ob der thread beendet wurde. mir ist es nur wichtig, dass das formular nicht hängt, damit man den abbrechen button benutzen kann. (dieser setzt die variable ilch_stop auf true, das muss danach noch funktionieren). wie stelle ich das an ? habe jetzt schon lange im forum gesucht, luckies tutorial gelesen und weiß immer noch nicht genau wie ich das anstellen soll.

vielen dank schonmal ;)
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 14.01.06 19:20 
Da du das Tutorial schon gelesen hast, kennst du ja auch das Kapitel über die Klasse TThread. Nimm die, das ist wesentlich einfacher. Ich habe gestern damit meinen ersten Thread erstellt, und es ist wirklich einfach ;-)

_________________
We are, we were and will not be.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 14.01.06 19:31 
îch weiß nicht genau wie ich die verwenden soll, hast du grad mal n beispiel da ?
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Sa 14.01.06 19:34 
Guck mal auf der Homepage von Luckie. Da liegt nicht nur das Tutorial als .pdf, sondern auch ne .zip (oder wars .rar?). Da sind Beispiel-Programme drin.

_________________
We are, we were and will not be.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Sa 14.01.06 19:35 
ahh da sind die, ich hab schon überall gesucht, danke ;)

ok wirklich geholfen haben mir die beispiele nicht, weil da immer ein timeout drinnen ist und die prozedur bei mir auch beliebig lang dauern kann. von mir aus tage.
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: So 15.01.06 09:27 
Etwas wichtiges hast du aber vergessen. Wenn du auf Kompos aus einem Thread zugreifst, musst du den zugriff synchronisieren ;).

PS: Guck einfach bei unserem Project in den Source, dann siehste das mit TThread.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: So 15.01.06 10:07 
bis jetzt sieht das ganze so aus:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
unit Unit4;

interface

uses
  windows, sysutils, Classes;

type
  UploadThread = class(TThread)
  private
    procedure UpdateCaption;
    procedure GetDir(dir: string);
  protected
    procedure Execute; override;
  end;

var
  ccap: string;  

implementation

uses UMain;

procedure UploadThread.UpdateCaption;
begin
  MainForm.L_File.Caption := ccap;
end;

{ Wichtig: Methoden und Eigenschaften von Objekten in visuellen Komponenten dürfen
  nur in einer Methode namens Synchronize aufgerufen werden, z.B.

      Synchronize(UpdateCaption);

  und UpdateCaption könnte folgendermaßen aussehen:

    procedure UploadThread.UpdateCaption;
    begin
      Form1.Caption := 'Aktualisiert in einem Thread';
    end; }


{ UploadThread }

procedure UploadThread.GetDir(dir: string);
var
  SearchRec: TSearchRec;
begin
  if ilch_stop then
    exit;
  if FindFirst(dir + '*.*', faAnyFile, SearchRec) = 0 then
  begin
    repeat
      if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then
      begin
        if (SearchRec.Attr and faDirectory) = faDirectory then
        begin
          ilch_CreateFTPFolder(SearchRec.Name);
          MainForm.IdFTP.ChangeDir(SearchRec.Name);
          GetDir(dir + SearchRec.Name + '\');
          MainForm.IdFTP.ChangeDirUp;
        end
        else
        begin
          ccap := 'Datei: ' + SearchRec.Name;
          Synchronize(UpdateCaption);
          MainForm.IdFTP.Put(dir + SearchRec.Name, SearchRec.Name);
        end;
      end;
    until FindNext(SearchRec) <> 0;
    FindClose(SearchRec);
  end;
end;

procedure UploadThread.Execute;
begin
  GetDir(ttdir);
end;

end.

Aufruf:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure UploadPerFTP(Directory, sub: string);
var
  dir: string;
  uthread: uploadthread;
begin
  dir := subpath;
  if dir <> '' then
  begin
    while Pos('/', dir) > 0 do
    begin
      Ilch_CreateFTPFolder(Copy(dir, 1, Pos('/', dir) - 1));
      MainForm.idFTP.ChangeDir(Copy(dir, 1, Pos('/', dir) - 1));
      Delete(dir, 1, Pos('/', dir));
    end;
  end;
  dir := directory;
  if dir[Length(dir)] <> '\' then dir := dir + '\';
  ttdir := dir;
  uthread := uploadthread.Create(false);
  uthread.FreeOnTerminate := true;
  uthread.Priority := tpNormal;
  //uthread.waitfor;
end;

verkürzter aufruf davon:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  MainForm.ReadFTPData(AFTP);
  if ilch_FTPConnect(AFTP) then
  begin
    UploadPerFTP(zippath, subpath); //Das muss erst fertig sein, bevor es weitergeht
    installfile := extractfilepath(paramstr(0)) + 'auto_install.php';
    configfile := extractfilepath(paramstr(0)) + 'admin_config.php';
    if fileexists(installfile) then
      MainForm.idFTP.put(installfile, '') else
{...}

und das ganze wird wieder in einer anderen prozedur aufgerufen.
das ganze ist eine art installation und muss eben schrittweise ablaufen, deshalb muss ich warten.

waitfor ist nur nicht das was ich suche, es legt das ganze programm lahm bis der thread fertig ist (wie sleep eben), aber es soll nur die prozedur offen gehalten werden, also alle folgenden die nach dieser prozedur aufgerufen werden sollen warten.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 15.01.06 10:17 
Vielleicht so ein Gerüst?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.MyToDoList(ToDo: Integer);
begin
  case ToDo of
    1: // Starte Thread 1
    2: // starte Thread 2
    ...
  end;
end;
und in den Synchronize-Methoden der Threads rufst du dann MyToDoList mit dem nächsten Parameter auf. Also:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.SynchronizeThread1(...);
begin
  Label1.Caption := 'Thread1 fertig';
  MyToDoList(2);
end;

_________________
We are, we were and will not be.
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: So 15.01.06 10:19 
soll ich ne extra synchonsation einbauen oder wie ?
versteh ich irgendwie net so ganz :?
Heiko
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 3169
Erhaltene Danke: 11



BeitragVerfasst: So 15.01.06 10:19 
Ändere mal den Quelltext nen hierzu (ausschnitte poste ich hier nur ;) ):

ausblenden Delphi-Quelltext
1:
2:
var
  Go: Boolean=false; //global


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure UploadThread.Execute;
begin
  Go:=true;
  GetDir(ttdir);
  Go:=false;
end;


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  if Assigned(uthread) then
  begin
// vlt. noch hier uthread.Terminate
    while Go do
    begin
      Application.ProcessMessages
    end;
  end;
  uthread:=uploadthread.Create(false);
  uthread.FreeOnTerminate:=true;
  uthread.Priority:=tpNormal;


Ich hoffe ich habe nix vergessen ;).
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: So 15.01.06 10:56 
geht auch nicht, ich dachte daran, die prozedur aufzuspalten und den 2. teil beim onterminate aufzurufen, aber das macht das ganze programm kaputt. hmpf so ein dreck.
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: So 15.01.06 12:12 
user profile iconF34r0fTh3D4rk hat folgendes geschrieben:
ich hab schon überall gesucht
Offensichtlich nicht nach der richtigen Lösung.
www.delphi-forum.de/viewtopic.php?t=53879

Und was für eine verblüffende Ähnlichkeit die beiden Titel der Threads haben :roll:

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
F34r0fTh3D4rk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5285
Erhaltene Danke: 29

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: So 15.01.06 13:37 
da hatte ich probleme mit dem kompilieren, ich werde es aber demnächst nochmal versuchen ;)
Alni
ontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 205

Win 2000, XP, SuSe, Debian
D5 Prof, D7 Prof, Kylix
BeitragVerfasst: Mo 20.02.06 22:25 
TThread löst beim beenden das Ereignis onTerminate aus. Dort kannst du ja dann deinem Hauptprogramm "Bescheid" sagen, das es mit was "sinnvollem" weitermachen kann und nicht mehr auf einen "abbrechenklickenden" Benutzer warten soll ;)

_________________
MfG Alex