スレッド化されたFTPダウンロードを正しく行う(Indy / Android)

マウリシオリマ

FTPサーバーからファイルをダウンロードするためにIdFTPを作成しましたが、スレッド化しようとすると、AndroidOSの「ホスト名を解決しています...」でスタックしました。

スレッドなし(正常に動作):

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;

そして、私がこのソリューションに従って作成したスレッドコード

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ステータスは、「ホスト名を解決しています...」でスタックしていることを示します。正しくスレッド化するにはどうすればよいですか?

レミー・ルボー

OnAfterGetOnWorkEndイベントを使用している方法で使用する理由はありませんインディは同期しています。TIdFTP.Get()転送が終了するまで戻りません。エラーが発生すると、例外が発生します。

したがって、両方のイベントハンドラーを削除し、を呼び出すtry/finally代わりにtry/except使用しDisconnect()、発生Get()しない場合にのみダウンロードを処理します

OnWorkEndそしてOnStatusイベントは、呼び出した同じスレッドのコンテキストでトリガされ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;

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

リストビューの最初の行にダウンロードされた画像は、Androidを正しく表示する前にすべての画像をシャッフルします

分類Dev

Androidサービスがバックグラウンドで正しく実行されていません

分類Dev

Android:Zipがサーバーからダウンロードされ、正しく解凍されません

分類Dev

スクリプトを読み込めません。メトロサーバーを実行していること、またはバンドル「index.android.bundle」がリリース用に正しくパッケージ化されていることを確認してください

分類Dev

Android Studioで古いAndroidバージョンをダウンロードするにはどうすればよいですか?エミュレーターにキットカットを実行させたいのですが、ロリポップしか表示されません

分類Dev

AndroidエミュレータでローカルFTPサーバーからダウンロードするときにエラー「227パッシブモードに入る」/「接続が拒否されました」

分類Dev

Androidでダウンロードした後、ダウンロードしたファイルを開く

分類Dev

exec()の実行中にエラーが発生しました。コマンド:作業ディレクトリ:null環境:null-ルート化されていないデバイスでAndroidでバイナリを正しく実行する方法は?

分類Dev

生成されたBlobをIonic3でAndroidデバイスにダウンロードします

分類Dev

スピナードロップダウンの選択された値が表示されない-Android

分類Dev

Android:スピナーのドロップダウンリストをクリックしても変更しないでください

分類Dev

Android Gradleプラグイン3.4.0にアップグレードした後、クラスが難読化されなくなりました

分類Dev

アプリのダウンロードに使用されたAndroidマーケットを特定する方法

分類Dev

Android 3Dゲームでレンダーを実行するためのいくつかのスレッド。スレッドセーフ?

分類Dev

Androidエミュレータウィンドウが正しく表示されない

分類Dev

Android O:バックグラウンド実行は許可されていません:許可を得たカスタムブロードキャスト

分類Dev

AndroidでのFTPアップロードおよびダウンロード

分類Dev

DownloadMangerを使用したAndroidダウンロードキュー

分類Dev

Androidフォームでフィルタリングされたselect-optionのようなドロップダウンを行うにはどうすればよいですか?

分類Dev

Androidデバイス上のモバイルインターネットによって転送(アップロード/ダウンロード)されたデータを収集します

分類Dev

AndroidのGoogleドライブからGoogleスプレッドシートをダウンロードする

分類Dev

デバイスのディレクトリ全体としてAndroidサポートライブラリをダウンロードするにはどうすればよいですか?(PCではなくAndroidデバイス)

分類Dev

Java / Androidを使用したダウンロード速度の測定

分類Dev

Webview を使用した Android ダウンロード ファイル

分類Dev

いずれかのブラウザがAndroidにファイルを保存すると、ブロードキャストが送信されますか?Androidのブラウザで保存/ダウンロードしたファイルを傍受するにはどうすればよいですか?

分類Dev

Android:定期的に実行されUIタスクを実行するバックグラウンドスレッドを作成しますか?

分類Dev

フラグメントのonCreate()で作成されたAndroidハンドラーがUIスレッドでhandleMessage()を実行していません

分類Dev

Android Studioがプロジェクトを開くたびにGradleのバージョンをダウンロードしようとする

分類Dev

安全でないネットワークからPlayストアからアプリをダウンロードしたためにAndroidサービスがハッキングされる可能性があります

Related 関連記事

  1. 1

    リストビューの最初の行にダウンロードされた画像は、Androidを正しく表示する前にすべての画像をシャッフルします

  2. 2

    Androidサービスがバックグラウンドで正しく実行されていません

  3. 3

    Android:Zipがサーバーからダウンロードされ、正しく解凍されません

  4. 4

    スクリプトを読み込めません。メトロサーバーを実行していること、またはバンドル「index.android.bundle」がリリース用に正しくパッケージ化されていることを確認してください

  5. 5

    Android Studioで古いAndroidバージョンをダウンロードするにはどうすればよいですか?エミュレーターにキットカットを実行させたいのですが、ロリポップしか表示されません

  6. 6

    AndroidエミュレータでローカルFTPサーバーからダウンロードするときにエラー「227パッシブモードに入る」/「接続が拒否されました」

  7. 7

    Androidでダウンロードした後、ダウンロードしたファイルを開く

  8. 8

    exec()の実行中にエラーが発生しました。コマンド:作業ディレクトリ:null環境:null-ルート化されていないデバイスでAndroidでバイナリを正しく実行する方法は?

  9. 9

    生成されたBlobをIonic3でAndroidデバイスにダウンロードします

  10. 10

    スピナードロップダウンの選択された値が表示されない-Android

  11. 11

    Android:スピナーのドロップダウンリストをクリックしても変更しないでください

  12. 12

    Android Gradleプラグイン3.4.0にアップグレードした後、クラスが難読化されなくなりました

  13. 13

    アプリのダウンロードに使用されたAndroidマーケットを特定する方法

  14. 14

    Android 3Dゲームでレンダーを実行するためのいくつかのスレッド。スレッドセーフ?

  15. 15

    Androidエミュレータウィンドウが正しく表示されない

  16. 16

    Android O:バックグラウンド実行は許可されていません:許可を得たカスタムブロードキャスト

  17. 17

    AndroidでのFTPアップロードおよびダウンロード

  18. 18

    DownloadMangerを使用したAndroidダウンロードキュー

  19. 19

    Androidフォームでフィルタリングされたselect-optionのようなドロップダウンを行うにはどうすればよいですか?

  20. 20

    Androidデバイス上のモバイルインターネットによって転送(アップロード/ダウンロード)されたデータを収集します

  21. 21

    AndroidのGoogleドライブからGoogleスプレッドシートをダウンロードする

  22. 22

    デバイスのディレクトリ全体としてAndroidサポートライブラリをダウンロードするにはどうすればよいですか?(PCではなくAndroidデバイス)

  23. 23

    Java / Androidを使用したダウンロード速度の測定

  24. 24

    Webview を使用した Android ダウンロード ファイル

  25. 25

    いずれかのブラウザがAndroidにファイルを保存すると、ブロードキャストが送信されますか?Androidのブラウザで保存/ダウンロードしたファイルを傍受するにはどうすればよいですか?

  26. 26

    Android:定期的に実行されUIタスクを実行するバックグラウンドスレッドを作成しますか?

  27. 27

    フラグメントのonCreate()で作成されたAndroidハンドラーがUIスレッドでhandleMessage()を実行していません

  28. 28

    Android Studioがプロジェクトを開くたびにGradleのバージョンをダウンロードしようとする

  29. 29

    安全でないネットワークからPlayストアからアプリをダウンロードしたためにAndroidサービスがハッキングされる可能性があります

ホットタグ

アーカイブ