Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/185.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
正确进行线程化FTP下载(Indy/Android)_Android_Delphi_Ftp_Indy_Delphi 10.1 Berlin - Fatal编程技术网

正确进行线程化FTP下载(Indy/Android)

正确进行线程化FTP下载(Indy/Android),android,delphi,ftp,indy,delphi-10.1-berlin,Android,Delphi,Ftp,Indy,Delphi 10.1 Berlin,我已经做了一个IdFTP从我的FTP服务器下载文件,但是当我试图使它线程化时,它在解析主机名时卡住了。。。在Android操作系统中 无螺纹工作良好: uses ..., IdFTPCommon; var RecordDownload: TMemoryStream; uses System.IOUtils; procedure TForm1.Button1Click(Sender: TObject); begin IdFTP1.Host := 'motoristaajudante.

我已经做了一个IdFTP从我的FTP服务器下载文件,但是当我试图使它线程化时,它在解析主机名时卡住了。。。在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;
我编写的线程代码如下:


然后FTP状态显示它在解析主机名时卡住了。。。。如何使其正确线程化?

没有理由像使用OnAfterGet和OnWorkEnd事件那样使用它们。印地是同步的。在传输完成之前,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;

没有理由按照您使用OnAfterGet和OnWorkEnd事件的方式使用它们。印地是同步的。在传输完成之前,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;

谢谢你,雷米,它工作得很好,给我一个处理下载错误的方法。谢谢你,雷米,它工作得很好,给我一个处理下载错误的方法。