Как загрузить файлы в Azure в фоновом режиме с Delphi и OmniThread? - PullRequest
5 голосов
/ 26 марта 2012

Я попытался загрузить +100 файлов в Azure с Delphi. Однако вызовы блокируют основной поток, поэтому я хочу сделать это с помощью асинхронного вызова или фонового потока.

Это то, что я делаю сейчас (например, объяснено здесь ):

procedure TCloudManager.UploadTask(const input: TOmniValue;
  var output: TOmniValue);
var
  FileTask:TFileTask;
begin
  FileTask := input.AsRecord<TFileTask>;

  Upload(FileTask.BaseFolder, FileTask.LocalFile, FileTask.CloudFile);
end;

function TCloudManager.MassiveUpload(const BaseFolder: String;
  Files: TDictionary<String, String>): TStringList;
var
  pipeline: IOmniPipeline;
  FileInfo : TPair<String,String>;
  FileTask:TFileTask;
begin
  // set up pipeline
  pipeline := Parallel.Pipeline
    .Stage(UploadTask)
    .NumTasks(Environment.Process.Affinity.Count * 2)
    .Run;
  // insert URLs to be retrieved
  for FileInfo in Files do
  begin
    FileTask.LocalFile := FileInfo.Key;
    FileTask.CloudFile := FileInfo.Value;
    FileTask.BaseFolder := BaseFolder;

    pipeline.Input.Add(TOmniValue.FromRecord(FileTask));
  end;//for

  pipeline.Input.CompleteAdding;

  // wait for pipeline to complete
  pipeline.WaitFor(INFINITE);
end;

Однако и этот блок тоже (почему? Я не понимаю).

Ответы [ 2 ]

4 голосов
/ 26 марта 2012

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

Правильный способ сделать это -

  1. Сохранение интерфейса, возвращенного из Parallel.Pipeline, в глобальном хранилище (например, в поле TCloudManager).
  2. График работы до трубопровода.
  3. Не ждите завершения, а назначьте обработчик OnStop и выполните любую необходимую очистку здесь (не забудьте обнулить глобальное хранилище, содержащее интерфейс конвейера).

Для выполнения шага 3 вам потребуется свежая библиотека OmniThreadLibrary из SVN , потому что я только что добавил эту функцию:)

procedure TCloudManager.MassiveUpload(const BaseFolder: String;
  Files: TDictionary<String, String>);
var
  FileInfo : TPair<String,String>;
  FileTask:TFileTask;
begin
  // set up pipeline
  FPipeline := Parallel.Pipeline
    .Stage(UploadTask)
      .NumTasks(Environment.Process.Affinity.Count * 2)
    .OnStop(
      procedure begin
        ShowMessage('All done');
        FPipeline := nil;
      end)
    .Run;
//   insert URLs to be retrieved
  for FileInfo in Files do
  begin
    FileTask.LocalFile := FileInfo.Key;
    FileTask.CloudFile := FileInfo.Value;
    FileTask.BaseFolder := BaseFolder;

    FPipeline.Input.Add(TOmniValue.FromRecord(FileTask));
  end;//for
  FPipeline.Input.CompleteAdding;
end;
0 голосов
/ 26 марта 2012

Delphi имеет вариант .NET, верно?Знали ли вы, что существует управляемый API .NET для службы хранилища Azure?

В классе CloudBlockBlob есть асинхронный вариант для загрузки / выгрузки и т. Д.

http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.storageclient.cloudblockblob_methods.aspx

...