2012-03-25 10 views
5

Próbowałem przesłać +100 plików do lazuru z Delphi. Jednak połączenia blokują główny wątek, więc chcę to zrobić z połączeniem asynchronicznym lub z wątkiem tła.Jak przesłać pliki do lazuru w tle za pomocą Delphi i OmniThread?

To co mam teraz zrobić (jak 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; 

Jednak ten blok zbyt (dlaczego ja nie rozumiem?).

Odpowiedz

4

Te bloki ponieważ dzwonisz waitfor który czeka na wszystkich etapach rurociągu, aby zakończyć swoją pracę. Podczas tego oczekiwania GUI jest zablokowany.

właściwy sposób zrobić to

  1. interfejs sklepu wrócił z Parallel.Pipeline w globalnej pamięci (na przykład w polu TCloudManager).
  2. Zaplanuj pracę na rurociągu.
  3. Nie czekajNa koniec, ale przypisz procedurę obsługi OnStop i wykonaj wszystkie czynności, których potrzebujesz tutaj (nie zapomnij zlikwidować magazynu globalnego z interfejsem potoku).

Aby zrobić krok 3 musisz świeże OmniThreadLibrary z SVN bo po prostu dodaje tę funkcjonalność :)

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

Wspaniale cię tu widzieć. Czy rurociąg jest odpowiednim narzędziem do tego? – mamcx

+0

Niezupełnie. Po prostu zrobiłbym Parallel.ForEach. – gabr

+0

Próbuję również z Parallel.ForEach, ale muszę wstawić Application.ProcessMessages() i nie było płynne. Być może dlatego, że nie rozumiem korzystania z biblioteki ... – mamcx

-5

Delphi ma wariant .NET, prawda? Czy wiesz, że istnieje interfejs API zarządzanego .NET dla usługi Azure Storage Service?

Klasa CloudBlockBlob ma wariant asynchronicznej za upload/download, itp

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

+0

Tak, istnieje, ale muszę to w rodzimej Delphi. – mamcx

+2

-1. Nie ma to absolutnie nic wspólnego z pytaniem tutaj zadanym i nie powinno być wysłane jako odpowiedź. –

+0

Ken - jak myślisz? Jeśli używa Delphi.NET, dałem mu bibliotekę, która jest na miejscu - możliwość asynchronicznego przesyłania wielu plików. – sebastus

Powiązane problemy