Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.05.2012, 21:18   #1
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
Вопрос Скачивание файлов в цикле через поток

Написал следующий код
Код:
...
type
  // Поток для загрузки файлов
  TDownLoader_Thread = class(TThread)
  private
    { Private declarations }
    Progress: Integer;
    FSL: TStringList;
  protected
    procedure Execute; override;
    procedure SyncProc;
  public
    property SL: TStringList read FSL;
  end;
...
var
  Form1: TForm1;
  DownLoader_Thread: TDownLoader_Thread;
  CriticalSection: TCriticalSection;
...
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin
  SL := TStringList.Create;
  SL.Add('Files\1.bmp');
  SL.Add('Files\1.docx');
  SL.Add('Files\1.rar');
  SL.Add('Files\1.txt');

  RepairFiles(SL);
  SL.Free;
end;
//--------------------------------Загрузка файлов-------------------------------
procedure TForm1.RepairFiles(Files: TStringList);
begin
  ProgressBar2.Position := Files.Count;

  CriticalSection := TCriticalSection.Create;

  DownLoader_Thread := TDownLoader_Thread.Create(True);
  DownLoader_Thread.FSL := Files;
  DownLoader_Thread.FreeOnTerminate := True;
  DownLoader_Thread.Resume;

  //!//CriticalSection.Free;
end;

procedure TDownLoader_Thread.Execute;
var
  HTTP: TIdHTTP;
  MS: TMemoryStream;
  i: Integer;
begin
  HTTP := TIdHTTP.Create(nil);
  MS := TMemoryStream.Create;

  CriticalSection.Enter;

  for i := 0 to FSL.Count - 1 do
  begin
    try
      try
        HTTP.Get('http://77.108.194.247/' + StringReplace(FSL.Strings[i], '\', '/', [rfReplaceAll, rfIgnoreCase]), MS);
        MS.SaveToFile(ExtractFilePath(Application.ExeName) + FSL.Strings[i]);
      except
      end;
    finally
      HTTP.Free;
      MS.Free;
    end;

    Progress := i;

    Synchronize(SyncProc);
  end;

  CriticalSection.Leave;
end;

procedure TDownLoader_Thread.SyncProc;
begin
  Form1.ProgressBar2.Position := Progress + 1;
end;
В начале загрузки появляется ошибка. В проекте ни на какую строку указания нет. Где была допущена ошибка?

Нашёл место ошибки, но не знаю как исправить.
Изображения
Тип файла: jpg pic.jpg (37.7 Кб, 133 просмотров)
Тип файла: jpg pic2.jpg (127.9 Кб, 97 просмотров)

Последний раз редактировалось Shouldercannon; 05.05.2012 в 22:00.
Shouldercannon вне форума Ответить с цитированием
Старый 05.05.2012, 22:10   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
TMemoryStream;
Почему через него?
Все мои качалки выглядят примерно так:
Код:
var fl:TFileStream;
begin
  ForceDirectories(FolderName);
  FolderName:=FolderName+FileName;
  fl:=TFileStream.Create(FolderName,fmCreate);
   IdHTTP1.Get(UrlLoad,fl);
  fl.Free;
 end;
end;
Цитата:
FSL
А что ему присваивается? Посмотри внимательно:
Цитата:
RepairFiles(SL);
SL.Free;
У тебя запущен отдельный поток. Работа RepairFiles не останавливает основной поток, и во время отработки сопроцесса ты выполняешь
Код:
SL.Free;
Как себя сопроцесс чувствовать будет?
Делай SL.Free; в конце обработки сопроцесса.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 05.05.2012, 22:44   #3
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Можно и делать sl.free
Но тогда в Нити (thread) создать стринглист FSL и написать
Код:
DownLoader_Thread.FSL.Assign(Files);
потом ессно free по окончанию работы

Тогда не будет зависимости, а каждый будет располагать собственными данными

Ещё малость не нравится подход с обращением к полю FSL класса нити - ведь и проперть даже есть - оберните в неё.
phomm вне форума Ответить с цитированием
Старый 05.05.2012, 23:01   #4
Shouldercannon
Участник клуба Подтвердите свой е-майл
 
Аватар для Shouldercannon
 
Регистрация: 26.01.2008
Сообщений: 1,897
По умолчанию

Теперь по другому сделал. Работает нормально.
Код:
...
  private
    { Private declarations }
    procedure CheckFiles;
  public
    { Public declarations }
  end;

type
  TFileList = record
    sFile: string;
    Hash: string;
  end;

type
  // Поток для получения списка файлов с их хэш-суммой с сервера
  TGetFiles_Thread = class(TThread)
  private
    { Private declarations }
    s: string;
    B: Boolean;
  protected
    procedure Execute; override;
    procedure SyncProc;
  public
  end;

type
  // Поток для загрузки файлов
  TDownLoader_Thread = class(TThread)
  private
    { Private declarations }
    Progress: Integer;
    FSLRepairFiles: TStringList;
  protected
    procedure Execute; override;
    procedure SyncProc;
  public
    property SLRepairFiles: TStringList read FSLRepairFiles;
  end;

var
  Form1: TForm1;
  FileList: array[0..255] of TFileList;
  FileListCount: Integer;
  GetFiles_Thread: TGetFiles_Thread;
  DownLoader_Thread: TDownLoader_Thread;
  CriticalSection: TCriticalSection;
  SLRepairFiles: TStringList;

implementation

{$R *.dfm}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  CriticalSection.Free;
  SLRepairFiles.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  CriticalSection := TCriticalSection.Create;
  SLRepairFiles := TStringList.Create;
end;

procedure TForm1.CheckFiles;
var
  i, res: Integer;
  MD5: TIdHashMessageDigest5;
  sFile: TFileStream;
  B: Boolean;
begin
  Memo1.Clear;
  Memo2.Clear;
  SLRepairFiles.Clear;

  ProgressBar1.Max := FileListCount;

  // Ищем в цикле отсутсвующие и изменённые файлы
  for i := 0 to FileListCount - 1 do
  begin
    B := True;

    Memo1.Lines.Add(ExtractFilePath(Application.ExeName) + FileList[i].sFile); // Проверяемый файл //!// В финальной версии убрать строку

    // Поиск отсутсвующих файлов
    if not FileExists(ExtractFilePath(Application.ExeName) + FileList[i].sFile) then
    begin
      SLRepairFiles.Add(FileList[i].sFile);
      Memo2.Lines.Add(ExtractFilePath(Application.ExeName) + FileList[i].sFile); // Отсутсвующий файл //!// В финальной версии убрать строку
      B := False; // Файл не найден
    end;

    // Поиск изменённых файлов
    if B then
    begin
      MD5 := TIdHashMessageDigest5.Create;
      sFile := TFileStream.Create(ExtractFilePath(Application.ExeName) + FileList[i].sFile, fmOpenRead or fmShareDenyNone);

      if not (MD5.AsHex(MD5.HashValue(sFile)) = FileList[i].Hash) then
      begin
        SLRepairFiles.Add(FileList[i].sFile);
        Memo2.Lines.Add(ExtractFilePath(Application.ExeName) + FileList[i].sFile); // Изменённый файл //!// В финальной версии убрать строку
      end;

      MD5.Free;
      sFile.Free;
    end;

    ProgressBar1.Position := i + 1;
  end;

  Caption := 'Убито файлов: ' + IntToStr(SLRepairFiles.Count);

  // Запрос на восстановление файлов
  if SLRepairFiles.Count > 0 then
  begin
    res := MessageBox(0, 'Восстановить повреждённые или отсутсвующие файлы', 'Вопрос', MB_YESNO or MB_ICONQuestion or MB_DEFBUTTON1);
    case res of
    IDYES: begin
      ProgressBar2.Max := SLRepairFiles.Count;

      DownLoader_Thread := TDownLoader_Thread.Create(True);
      DownLoader_Thread.FSLRepairFiles := SLRepairFiles;
      DownLoader_Thread.FreeOnTerminate := True;
      DownLoader_Thread.Resume;
    end;

    end;
  end;
end;
//--------------------------------Загрузка файлов-------------------------------
procedure TDownLoader_Thread.Execute;
var
  HTTP: TIdHTTP;
  FS: TFileStream;
  i: Integer;
  Folder: string;
begin
  HTTP := TIdHTTP.Create(nil);

  CriticalSection.Enter;

  for i := 0 to FSLRepairFiles.Count - 1 do
  begin
    Folder := ExtractFilePath(Application.ExeName) + ExtractFilePath(FSLRepairFiles.Strings[i]);
    ForceDirectories(Folder);
    try
      try
        FS := TFileStream.Create(Folder + ExtractFileName(FSLRepairFiles.Strings[i]), fmCreate);
        HTTP.Get('http://77.108.194.247/' + StringReplace(FSLRepairFiles.Strings[i], '\', '/', [rfReplaceAll, rfIgnoreCase]), FS);
      except
      end;
    finally
      FS.Free;
    end;

    Progress := i + 1;

    Synchronize(SyncProc);
  end;

  CriticalSection.Leave;

  HTTP.Free;
end;

procedure TDownLoader_Thread.SyncProc;
begin
  Form1.ProgressBar2.Position := Progress;
  if FSLRepairFiles.Count = Progress then Form1.Caption := 'Восстановлено: ' + IntToStr(FSLRepairFiles.Count) + ' файлов';
end;

Последний раз редактировалось Shouldercannon; 05.05.2012 в 23:05.
Shouldercannon вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Скачивание файлов в поддиректории user__ PHP 7 11.12.2011 21:28
Скачивание файлов в поддиректории user__ HTML и CSS 2 08.12.2011 13:48
Копирование n файлов через поток. Проблема Человек_Борща Общие вопросы Delphi 6 29.05.2011 09:22
Скачивание файлов из инета jkpro Работа с сетью в Delphi 10 12.09.2009 17:07
скачивание файлов с FTP L.Morgan Работа с сетью в Delphi 2 14.04.2009 10:14