Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > IdFTP - подвисает при закачке


Автор: inside 21.7.2006, 23:26
Ребят, извините, если вопрос глупый. Считаю в процентах кол-во закаченного файла.

Код

procedure TForm3.IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
var f: real;
begin
   f:=AWorkCount/max_bytes;
   f:=Round(f*100);
   StatusBar1.SimpleText:='Загружено '+FloatToStr(f)+'%';
   Form3.Refresh;
end;


max_bytes - общий размер файла

Вот только со временем, при закачке большого файла - прога виснет, но по завершении закачки отвисает. Как решить проблему? 

Автор: Nickey 22.7.2006, 00:44
ЭЭЭ,в отдельный поток может ее пихнуть? 

Автор: Matematik 22.7.2006, 13:10
Поиграй настройками антифриза 

Автор: inside 22.7.2006, 19:43
А что такое антифриз? Не слышал про это =(

В отдельный поток засунуть поможет? 

Автор: Snowy 23.7.2006, 13:54
Просто найди TIdAntifreeze, брось его на форму. 

Автор: inside 27.8.2006, 20:40
Всем ещё раз привеееет =)))

Народ, я поробовал AntiFreeze - ничего не получилось - прочитал, что он подтормаживает.. Решил поэтому сделать отдельным потоком.. Вроде нормально получилось, вот только такой вопрос - как теперь обработать события OnWork & OnWorkBegin & OnWorkEnd...????  smile

Дело в том, что я хочу отслеживать процесс закачки.. Кстати - в новом процессе я использую такой код. Всё ли правильно?!

Код

unit Unit5;

interface

uses
  Classes, IdFTP;

type
  MThread = class(TThread)
  private
    RFilePath: string;
  protected
    procedure upload(FilePath: string);
    procedure Execute; override;
  public
    property FilePath: string write RFilePath;
  end;

implementation

uses Unit3;

procedure MThread.upload(s: string);
var ftp: TIdFTP;
begin
    ftp:=TIdFTP.Create(nil);
    with ftp do begin
        Username:='nick';
        Password:='password';
        Host:='www.domen.ru';
        ftp.OnConnected:=???;
        ftp.OnWorkEnd:=???;
        ftp.OnWork:=???;
        ftp.OnWorkBegin:=???;
        Connect;
        Put(s, s);
        Disconnect;
    end;
    ftp.Free;
end;

procedure MThread.Execute;
begin
   Synchronize(upload(FilePath));
end;

end.


Пробовал просто приравнять их к процедурам - обработчикам событий. если писать через VCL... Но говорит о несовпадении типов TNotifyEvent & procedure    smile 

Автор: Snowy 27.8.2006, 21:44
Правильно. Потому что процедура должна быть с параметром:
Код

  public
    procedure OnConnect(Sender: TObject);

Автор: inside 27.8.2006, 22:47
А если параметры оставить те же, что и в обработчиках событий в VCL:

procedure IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);

они передадутся в резльтате такого равенства:

ftp.OnWork=IdFTP1Work????

только вот ещё проблема в том, что компилятор не понимает, что такое AWorkMode.... Где есть эта запись?

Спасибо!!  smile 

Автор: Snowy 27.8.2006, 22:59
Именно. При присваивании событию, обработчик должен иметь параметры, соответствующие ожидаемых компонентом.
При этом имена переменных могут отличаться - главное количество, порядок и тип параметров.

TWorkMode находится в IdComponent.

Автор: inside 27.8.2006, 23:19
Snowy, блииииииин, точняяяяяк =))) Спасибо огромное! Побежал пробовать

Автор: inside 29.8.2006, 13:07
ну в общем я оформил новый поток:

Код

type
  MThread = class(TThread)
  private
    RFileSource: string;
    RFileName: string;
  protected
    procedure upload;
    procedure Execute; override;
    procedure FTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
    procedure FTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer);
    procedure FTPConnected(Sender: TObject);
    procedure FTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
  public
    property FileSource: string write RFileSource;
    property FileName: string write RFileName;
  end;

var max_bytes: integer;

implementation

uses Unit3, SysUtils;

procedure MThread.FTPConnected(Sender: TObject);
begin
   Form3.StatusBar1.SimpleText:='Connected!';
end;

procedure MThread.FTPWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
begin
   Form3.StatusBar1.SimpleText:='Done';
end;

procedure MThread.FTPWork(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
var f: real;
begin
   f:=AWorkCount/max_bytes;
   f:=Round(f*100);
   Form3.StatusBar1.SimpleText:='Загружено '+FloatToStr(f)+'%';
   Form3.Refresh;
end;

procedure MThread.FTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Integer);
begin
   max_bytes:=AWorkCountMAx;
end;

procedure MThread.upload;
var ftp: TIdFTP;
begin
    ftp:=TIdFTP.Create(nil);
    with ftp do begin
        Username:='...';
        Password:='...';
        Host:='domen';
        ftp.OnConnected:=FTPConnected;
        ftp.OnWorkEnd:=FTPWorkEnd;
        ftp.OnWork:=FTPWork;
        ftp.OnWorkBegin:=FTPWorkBegin;
        Connect;
        Put(RFileSource, RFileName);
        Disconnect;
    end;
    ftp.Free;
end;

procedure MThread.Execute;
var path: string;
begin
   Synchronize(upload);
end;

end.

вызываю поток следующий кодом:

  NewThread := MThread.Create(True);
  NewThread.FreeOnTerminate := True;
  try
        NewThread.FileSource := s;
        NewThread.FileName := name;
        NewThread.Resume;
  except
      NewThread.Free;
  end;


Но что-то программа всё равно подвисает.. Цыферки в статус баре один то обновляются, то подвисают. Само окно вообще всё виснет. В чём косяк. Где я напортачил?  smile 

Автор: Snowy 29.8.2006, 13:32
А зачем ты аплод запихал в синхронизацию? Так он у тебя в основном потоке работать будет.
Просто вызови его. Иначе смысла в треде никакого.

Автор: inside 29.8.2006, 13:35
 smile  smile  smile 

А в синхронизацию запихать только обновление статус бара?????  smile 

ээээ.. вот только как это сделать?! Ведь обработчики событий тогда буду вызываться в другом потоке... а оттуда нет доступа к элементам VCL... 

Автор: Snowy 29.8.2006, 14:02
Сделай ещё одну процедуру для обновления контролов и вызывай её синхронизацией из OnWork.

Добавлено @ 14:03 
Цитата(inside @  29.8.2006,  13:35 Найти цитируемый пост)
а оттуда нет доступа к элементам VCL... 
Вообще-то доступ есть... Просто не рекомендуется его юзать. Но и не запрещено...

Автор: inside 29.8.2006, 22:20
Точняк - всё сделал и всё работает отлично...

Но... вот ещё один вопросец... smile 

У меня происходит закачка файла... я хочу сделать возможность её отмены.. Но часть файла уже закачивается на сервер и я хочу сделать, чтобы при нажатии отмены этот кусок удалялся. При нажатии отмены я вызываю метод Terminate. Вот только как мне обработать закрытие и удалить файл - ведь Terminated я не могу проверять, разве что в событии OnWork... (Если можно там, то можно ли просто взять и из этой процедуры удалить файл и закрыть поток?!  smile )

Автор: Snowy 30.8.2006, 09:27
Удаляй в Thread.Execute, если есть флаг Terminated/ После вызова Upload.

Автор: inside 30.8.2006, 10:04
Но ведь тогда у меня сначала закачается файл полностью, а потом я его удалю. А мне надо отменить закачку в процессе.

Execute такой

Код

begin
ftp:=TIdFTP.Create(nil);
    with ftp do begin
        Username:='...';
        Password:='...';
        Host:='...';
        ftp.OnConnected:=FTPConnected;
        ftp.OnWorkEnd:=FTPWorkEnd;
        ftp.OnWork:=FTPWork;
        ftp.OnWorkBegin:=FTPWorkBegin;
        Connect;
        Put(RFileSource, RFileName);
        Disconnect;
    end;
    ftp.Free;
end;


Если я проверю свойство Terminated после Put, то у меня наверное сначала файл закачается, а потом уже отмена произойдет. Верно. Ещё раз спрошу - может можно в методе OnWork?


Автор: Snowy 30.8.2006, 10:07
Сделай Abort smile

Автор: inside 31.8.2006, 17:43
Не получаеться =(((

вот процедура

Код

procedure MThread.FTPWork(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
begin
   f:=Round(AWorkCount/max_bytes*100);
   if Terminated then begin
      ftp.Abort;
      ShowMessage(IntToStr(ftp.Size(RFileName)));
      ShowMessage('Proccess killed!');
      end;
   Synchronize(make_corr);
end;


когда посылаешь команду Thread.Terminate не появляется никакое сообщение...

Если ShowMessage('Proccess killed!') поставить перед ftp.Abort то появляется => ftp.Abort провоцирует какую-то ошибку.... =(( Что делать, Snowy?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)