Поддержание N одновременных загрузок HTTP - PullRequest
3 голосов
/ 01 октября 2010

У меня есть приложение, которое запрашивает веб-сервис по диапазону дат.Веб-сервис возвращает список GUID.Затем я беру каждый GUID и загружаю WAV-файл, который ему тоже соответствует.Прямо сейчас я делаю это один за другим и отлично работает.То, что я хотел бы сделать, это загрузить до N файлов WAV одновременно.По какой-то причине я просто не могу понять хороший способ сделать это.

Я использую IP * Works (n / Software) компонент TipwHTTP (async).

У кого-нибудь есть предложения подтолкнуть меня в правильном направлении.

1 Ответ

7 голосов
/ 01 октября 2010

Поместите каждую загрузку в отдельный поток и управляйте этим списком загрузок. Например, вы можете использовать OmniThreadLibrary , чтобы упростить программирование потоков. Вы также можете посмотреть на мой потоковый блок на Cromis , что намного проще, но этого может быть достаточно для вашего случая. Это очень удобно.

Если вам не нравятся потоки, вы также можете создать исполняемый файл, который при запуске принимает входные параметры и загружает контент в указанное место.

Просто отметьте, что одновременная загрузка многих файлов, вероятно, поможет, только если вы загружаете из разных источников, если нет, вы все равно будете ограничены пропускной способностью вашего единственного источника, а также накладными расходами на потоки.

Вот код с моим модулем потоков и Indy для HTTP, например, потому что его легко понять:

procedure TfMain.FormCreate(Sender: TObject);
var
  Task: ITask;
begin
  FTaskPool.DynamicSize := cbDynamicPoolSize.Checked;
  FTaskPool.MinPoolSize := StrToInt(ePoolSize.Text);
  FTaskPool.OnTaskMessage := OnTaskMessage;
  FTaskPool.Initialize;

  for I := 1 to NumberOfDownloads do
  begin
    Task := FTaskPool.AcquireTask(OnTaskExecute, 'HTTPDownload');
    Task.Values.Ensure('TargeFile').AsString := aFileName;
    Task.Values.Ensure('URL').AsString := aDownloadURL;
    Task.Run;
  end;
end;

procedure TfMain.OnTaskExecute(const Task: ITask);
var
  HTTPClient: TIdHTTP;
  FileStream: TFileStream;
begin
  HTTPClient := TIdHTTP.Create(nil);
  try
    FileStream := TFileStream.Create(Task.Values.Get('TargeFile').AsString, fmCreate);
    try
      HTTPClient.Get(Task.Values.Get('URL').AsInteger, FileStream);
      Task.Message.Ensure('Result').AsString := 'Success';
      Task.SendMessageAsync;
    finally
      FileStream.Free;
    end;   
  finally
    HTTPClient.Free;
  end;
end;

procedure TfMain.OnTaskMessage(const Msg: ITaskValues);
begin
  // do something when a single download has finished
end;
...