2017-10-06 27 views
1

私は自分のFTPサーバーからファイルをダウンロードするためにIdFTPを作ったが、それをスレッド化しようとするとAndroid OSの "解決するホスト名..."スレッドなし正しくスレッド化されたFTPをダウンロードする(Indy/Android)

(細かい作業):

uses ..., IdFTPCommon; 

var 
    RecordDownload: TMemoryStream; 

uses System.IOUtils; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    IdFTP1.Host := 'motoristaajudante.ddns.net'; 
    IdFTP1.Port := 2121; 
    IdFTP1.DataPortMin := 50100; 
    IdFTP1.DataPortMax := 51100; 
    IdFTP1.Username := 'anonymous'; 
    IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary; 
    IdFTP1.Passive := True; 
    try 
    IdFTP1.Connect(); 
    IdFTP1.Get('00001.m4a',TPath.GetDocumentsPath + PathDelim + '00001.m4a',True,False); 
    except 
    IdFTP1.Disconnect; 
    end; 
end; 

procedure TForm1.IdFTP1AfterGet(ASender: TObject; AStream: TStream); 
begin 
    IdFTP1.Disconnect; 
end; 

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode); 
begin 
    if FileExists(TPath.GetDocumentsPath + PathDelim + '00001.m4a') then 
    begin 
     ShowMessage('Downloaded!'); 
    end; 
end; 

そして、私はthis solutionを以下の作っスレッドコード:

uses ..., IdFTPCommon; 

type 
    TLoadThread = class(TThread) 
    public 
    constructor Create; reintroduce; 
    protected 
    procedure Execute; override; 
    end; 

type 
    TForm1 = class(TForm) 
    ... 
    procedure ThreadTerminated(Sender: TObject); 

var 
    RecordDownload: TMemoryStream; 
    Loading: Boolean = False; 
    zLThread: TLoadThread = nil; 

uses System.IOUtils; 

constructor TLoadThread.Create; 
begin 
    inherited Create(True); 
    FreeOnTerminate := True; 
end; 

procedure TLoadThread.Execute; 
begin 
try 
    Form1.IdFTP1.Connect(); 
    Form1.IdFTP1.Get('00001.m4a',TPath.GetDocumentsPath + PathDelim + '00001.m4a',True,False); 
except 
    Form1.IdFTP1.Disconnect; 
end; 
end; 

procedure TForm1.ThreadTerminated(Sender: TObject); 
begin 
    zLThread := nil; 
    Loading := False; 
    FloatAnimation1.Enabled := False; 
    FloatAnimation2.Enabled := False; 
    Arc3.StartAngle := -90; 
    Arc3.EndAngle := 0; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    IdFTP1.Host := 'motoristaajudante.ddns.net'; 
    IdFTP1.Port := 2121; 
    IdFTP1.DataPortMin := 50100; 
    IdFTP1.DataPortMax := 51100; 
    IdFTP1.Username := 'anonymous'; 
    IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary; 
    IdFTP1.Passive := True; 
    zLThread := TLoadThread.Create; 
    zLThread.OnTerminate := ThreadTerminated; 
    zLThread.Start; 
    Loading := True; 
    FloatAnimation1.Enabled := True; 
    FloatAnimation2.Enabled := True; 
end; 

procedure TForm1.IdFTP1AfterGet(ASender: TObject; AStream: TStream); 
begin 
    IdFTP1.Disconnect; 
end; 

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode); 
begin 
    Form1.FloatAnimation1.Enabled := False; 
    Form1.FloatAnimation2.Enabled := False; 
    Form1.Arc3.StartAngle := -90; 
    Form1.Arc3.EndAngle := 0; 
    if FileExists(TPath.GetDocumentsPath + PathDelim + '00001.m4a') then 
    begin 
     ShowMessage('Downloaded!'); 
    end; 
end; 

procedure TForm1.IdFTP1Status(ASender: TObject; const AStatus: TIdStatus; 
    const AStatusText: string); 
begin 
    Memo1.Lines.Add(AStatusText); 
    Application.ProcessMessages; 
end; 

そして、それがで立ち往生FTPステータス・ショー "のホスト名を解決..."。正しくスレッド化するにはどうすればいいですか?

答えて

4

OnAfterGetOnWorkEndイベントを使用する理由はありません。インディは同期的です。 TIdFTP.Get()は転送が終了するまで戻りません。エラーが発生した場合は例外が発生します。だから、

Get()は上げていない場合にのみDisconnect()を呼び出して、ダウンロードを処理する代わりにtry/excepttry/finallyを使用し、両方のイベントハンドラを取り除きます。

OnWorkEndOnStatusイベントがConnect()Disconnect()、及びGet()を呼び出し、同じスレッドのコンテキスト内でトリガされます。だから、あなたのスレッドの例では、それはワーカースレッドであり、メインスレッドではありません。しかし、イベントハンドラはUIコントロールへのアクセスを同期していません。それは、あなたが経験しているフリーズを含む、あらゆる種類の問題を引き起こす可能性があります。 と同期する必要があります(TThread.OnTerminatedイベントが同期しています)。そうは言って

、代わりにこれを試してみてください。

は非スレッド:スレッド

uses 
    ..., IdFTPCommon; 

... 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    IdFTP1.Host := 'motoristaajudante.ddns.net'; 
    IdFTP1.Port := 2121; 
    IdFTP1.DataPortMin := 50100; 
    IdFTP1.DataPortMax := 51100; 
    IdFTP1.Username := 'anonymous'; 
    IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary; 
    IdFTP1.Passive := True; 
    try 
    IdFTP1.Connect; 
    try 
     IdFTP1.Get('00001.m4a', TPath.GetDocumentsPath + PathDelim + '00001.m4a', True, False); 
    finally 
     IdFTP1.Disconnect; 
    end; 
    ShowMessage('Downloaded!'); 
    except 
    ShowMessage('Error while downloading!'); 
    end; 
end; 

uses 
    ..., IdFTPCommon; 

type 
    TLoadThread = class(TThread) 
    public 
    constructor Create; reintroduce; 
    protected 
    procedure Execute; override; 
    end; 

type 
    TForm1 = class(TForm) 
    ... 
    IdFTP1: TIdFTP; 
    procedure ThreadTerminated(Sender: TObject); 
    ... 
    private 
    Loading: Boolean; 
    zLThread: TLoadThread; 
    end; 

... 

constructor TLoadThread.Create; 
begin 
    inherited Create(True); 
    FreeOnTerminate := True; 
end; 

procedure TLoadThread.Execute; 
begin 
    Form1.IdFTP1.Connect; 
    try 
    Form1.IdFTP1.Get('00001.m4a', TPath.GetDocumentsPath + PathDelim + '00001.m4a', True, False); 
    finally 
    Form1.IdFTP1.Disconnect; 
    end; 
end; 

procedure TForm1.ThreadTerminated(Sender: TObject); 
begin 
    zLThread := nil; 
    Loading := False; 
    FloatAnimation1.Enabled := False; 
    FloatAnimation2.Enabled := False; 
    Arc3.StartAngle := -90; 
    Arc3.EndAngle := 0; 
    If TThread(Sender).FatalException = nil then 
    ShowMessage('Downloaded!') 
    else 
    ShowMessage('Error while Downloading!'); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    IdFTP1.Host := 'motoristaajudante.ddns.net'; 
    IdFTP1.Port := 2121; 
    IdFTP1.DataPortMin := 50100; 
    IdFTP1.DataPortMax := 51100; 
    IdFTP1.Username := 'anonymous'; 
    IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary; 
    IdFTP1.Passive := True; 
    zLThread := TLoadThread.Create; 
    zLThread.OnTerminate := ThreadTerminated; 
    zLThread.Start; 
    Loading := True; 
    FloatAnimation1.Enabled := True; 
    FloatAnimation2.Enabled := True; 
end; 

procedure TForm1.IdFTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string); 
begin 
    TThread.Queue(nil, 
    procedure 
    begin 
     Memo1.Lines.Add(AStatusText); 
    end 
); 
end; 
+0

はあなたにレミーをありがとう、それは完全に作業し、プラス私に処理するための方法を与えるですダウンロードエラー。 –

関連する問題