2013-04-03 3 views
1

У меня есть проект FTP-загрузчика, который использует форму, созданную во время выполнения, чтобы начать загрузку на несколько FTP-серверов (используя Indy), моя проблема заключается в следующем (и мне действительно нужна ваша помощь).delphi Form с использованием нескольких экземпляров

На форме я ставлю IdFTP Component + Загрузка через кнопку + общие свойства с именем FTPSrvAdrs и SrcFile + TrgFolder как таким образом:

type 
    TFtpUploader = class(TForm) 
    IdFTP: TIdFTP; 
    StartUpload:TButton; 
    UploadProgress:TProgressBar; 
    procedure StartUploadClick(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    private 
    FFtpSrvAdrs:String; 
    FSrcFile:String; 
    FTargetFtpFld:String; 
    Procedure StartMyUpload(); 
    procedure SetFtpAdrs(const value:string); 
    procedure SetSrcFile(const value:string); 
    procedure SetTargetFtpFld(const value:string); 
    { Private declarations } 
    public 
    { Public declarations } 
    property FtpAdrs:string read FFtpSrvAdrs write SetFtpAdrs; 
    property SourceFile:string read FSrcFile write SetSrcFile; 
    property TargetFtpFld:string read FTargetFtpFld write SetTargetFtpFld; 
    end; 

var 
    FtpUploader: TFtpUploader; 

implementation 

    procedure TFtpUploader.StartUploadClick(Sender: TObject); 
    begin 
    StartMyUpload(); 
    end; 

    procedure TFtpUploader.SetFtpAdrs(const value: string); 
    begin 
    FFtpSrvAdrs:=value; 
    end; 

    procedure TFtpUploader.SetSrcFile(const value: string); 
    begin 
    FSrcFile:=value; 
    end; 

    procedure TFtpUploader.SetTargetFtpFld(const value: string); 
    begin 
    FTargetFtpFld:=value; 
    end; 

    procedure TFtpUploader.StartMyUpload; 
    var 
    FtpUpStream: TFileStream; 
    begin 
     ftpUpStream:= TFileStream.create(FSrcFile, fmopenread) 
    try 
    with IdFTP do begin 
     Host:= FFtpSrvAdrs; 
     Username:='MyUserName'; 
     Password:='MyPassword'; 
    end; 
    IdFTP.Connect(true, 1200) 
    IdFTP.Passive:= true; 
    IdFTP.ChangeDir(FTargetFtpFld) 
    IdFTP.Put(ftpUpStream,FSrcFile, false); 
    finally 
    ftpUpStream.Free; 
    end; 
    end; 


    procedure TFtpUploader.FormClose(Sender: TObject; var Action: TCloseAction); 
    begin 
    Action:=caFree; 
    end; 

Эта форма будет создана на RunTime (4 раза = 4 кнопки будут запустить его отдельно, как таким образом:

в главной форме я имею эту процедуру:

Procedure MainForm.UploadTo(FTPSrv,SrcFile,FtpTargetFld:String); 
     var 
     FUploadFrm:TFtpUploader; 
     begin 
      FUploadFrm:=TFtpUploader.Create(nil); 
      if assigned(FUploadFrm) then 
     begin 
      FUploadFrm.FtpAdrs:=FTPSrv; 
      FUploadFrm.SourceFile:=SrcFile; 
      FUploadFrm.TargetFtpFld:=FtpTargetFld; 
      FUploadFrm.Show; 
     end; 
     end; 

     procedure MainForm.Button1Click(Sender: TObject); 
     begin 
     UploadTo('MyFtpSrv_1','MySrcFile_1','MyFtpTargetFld_1'); 
     end; 

     procedure MainForm.Button2Click(Sender: TObject); 
     begin 
     UploadTo('MyFtpSrv_2','MySrcFile_2','MyFtpTargetFld_2'); 
     end; 

// same with other 2 buttons 

форма FtpUploader создается/открываемых (4 экземпляра s), ISSUE IS, когда я нажимаю кнопку StartUpload, процесс загрузки FTP не запускается во всех этих 4 экземплярах, но я должен ждать, что каждый процесс загрузки будет завершен (завершен), а другой будет автоматически запускаться, а это значит, что нет все процессы загрузки запускаются в одно и то же время.

спасибо.

+0

Вы не показали из 'TFtpUploader' кода и как мы можем догадаться? * Также вы создаете эти экземпляры, но где вы их освобождаете? Например, вы можете, например, сделать TFtpUploader.Create (Application) * –

+0

Например, для StartButton нет обработчика событий, поэтому он не должен реагировать ни на что. –

+0

привет, они освобождены при закрытии события следующим образом: 'code' procedure FtpUploader.FormClose (Sender: TObject; var Action: TCloseAction); начало Действие: = caFree; конец; 'code' – user2240395

ответ

1

Кажется, вам нужно либо сменить библиотеку Indy на некорректную библиотеку в фоновом режиме (на основе событий или на основе завершения), либо сделать вашу программу многопотоковой (с ее собственной проблемой, например, кнопку 20 раз или закрытие формы во время процесса или даже закрытие программы при запуске).

На основе http://otl.17slon.com/book/doku.php?id=book:highlevel:async это может выглядеть что-нибудь вроде этого:

TFtpUploader = class(TForm) 
    private 
    CanCloseNow: boolean; 

... 

    procedure TFtpUploader.FormClose(Sender: TObject; var Action: TCloseAction); 
    begin 
    if Self.CanCloseNow 
     then Action := caFree 
     else Action := caIgnore; 
    end; 

    procedure TFtpUploader.MyUploadComplete; 
    begin 
    Self.CanCloseNow := True; 
    Self.Close; 
    end; 

    procedure TFtpUploader.StartMyUpload; 
    begin 
    Self.CanCloseNow := false; 
    Self.Enabled := False; 
    Self.Visible := True; 
    Application.ProcessMessages; 

Parallel.Async(
    procedure 
    var 
    FtpUpStream: TFileStream; 
    begin 
    ftpUpStream:= TFileStream.create(FSrcFile, fmopenread) 
    try 
     with IdFTP do begin 
     Host:= FFtpSrvAdrs; 
     Username:='MyUserName'; 
     Password:='MyPassword'; 
     Connect(true, 1200) 
     Passive:= true; 
     ChangeDir(FTargetFtpFld) 

     // this does not return until uploaded 
     // thus would not give Delphi a chance to process buttons 
     // pressed on other forms. 
     Put(ftpUpStream,FSrcFile, false); 
    end; 
    finally 
     ftpUpStream.Free; 
    end; 
    end 
, 
    Parallel.TaskConfig.OnTerminated(
    procedure (const task: IOmniTaskControl) 
    begin 
     MyUploadComplete; 
    end; 
); 
end; 

Или вы можете использовать библиотеку AsyncCalls проще http://andy.jgknet.de/blog/bugfix-units/asynccalls-29-asynchronous-function-calls/

Смежные вопросы