【问题标题】:How upload files to azure in background with Delphi and OmniThread?如何使用 Delphi 和 OmniThread 在后台将文件上传到 azure?
【发布时间】:2012-03-25 20:26:23
【问题描述】:

我尝试使用 Delphi 将 +100 个文件上传到 azure。但是,调用阻塞了主线程,所以我想使用异步调用或后台线程来执行此操作。

这就是我现在所做的(比如explained here):

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;

但是这个块也是(为什么?我不明白)。

【问题讨论】:

    标签: multithreading delphi azure delphi-xe2 omnithreadlibrary


    【解决方案1】:

    这会阻塞,因为您正在调用 WaitFor 等待所有管道阶段完成它们的工作。在等待期间,GUI 被阻止。

    正确的做法是

    1. 将从 Parallel.Pipeline 返回的接口存储在全局存储中(例如在 TCloudManager 字段中)。
    2. 为管道安排工作。
    3. 不要 WaitFor 结束,而是分配 OnStop 处理程序并在此处执行您需要的任何清理工作(不要忘记清除保存管道接口的全局存储)。

    要执行第 3 步,您需要来自 SVN 的新 OmniThreadLibrary,因为我刚刚添加了此功能 :)

    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;
    

    【讨论】:

    • 并非如此。我只会做一个 Parallel.ForEach。
    • 我也尝试使用 Parallel.ForEach,但我需要插入 Application.ProcessMessages() 并且不流畅。可能是因为我对库的使用缺乏了解……
    • 现在运行良好,但我失去了更新主 GUI 的能力。我使用 Parallel.Async/OnTerminated...
    • 此类任务的更详细示例:thedelphigeek.com/2011/10/…
    【解决方案2】:

    Delphi 有一个 .NET 变体,对吗?您是否知道 Azure 存储服务有一个 .NET 托管 API?

    CloudBlockBlob 类有一个用于上传/下载等的异步变体。

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

    【讨论】:

    • 是的,存在,但我需要在原生 delphi 中使用它。
    • -1。这与此处提出的问题完全无关,不应该作为答案发布。
    • 肯 - 你怎么看?如果他使用的是 Delphi.NET,我给了他一个正确的库——异步上传大量文件的能力。
    • 因为 delphi 的 .net 变体称为 delphi prism (embarcadero.com/products/prism),而我发布的代码与 .net 完全不同。是纯原生的delphi(可能是非delphi开发者不知道的)
    • @Greg,他没有使用 Delphi.NET(不再存在,顺便说一句),问题是专门关于使用 OmniThreadLibrary。如果问题甚至有一个与 .NET 相关的标签,那么您的答案可能与远程相关,但事实并非如此。 (OmniThreadLibrary,顺便说一句,是一个免费的开源多线程库,用 Delphi 编写,也不与 .NET 相关。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2023-01-19
    • 2017-08-17
    • 1970-01-01
    • 2011-12-05
    • 2020-06-12
    相关资源
    最近更新 更多