2016-12-01 32 views
6

我的場景是,我有一個BufferBlock<Stream>接收來自外部來源的Stream,比方說文件系統或某個FTP服務器。這些文件Stream將傳遞到另一個塊並進行處理。TransformBlock發佈到輸出

唯一的問題是這些文件中的一部分是壓縮的,我想在中間添加一個Block,它將在必要時解壓縮文件,併爲其每個條目創建多個輸出Stream

但是我不想使用TransformBlockMany,因爲這意味着我必須完全收到ZIP Stream並一次創建輸出Stream數組。

我想這Block接收ZIP Stream,開始解壓縮,並Push下一個流每當進入準備,所以過程塊能夠儘快的第一個文件解壓開始處理,而不要等到一切都解壓縮。

我該如何解決這個問題?

+3

你使用什麼庫進行ZIP解壓縮? –

+2

使用System.IO.Compression.ZipFile。 – Gidon

+0

到目前爲止,我明白我的問題實際上是異步部分。如果我不使用異步,我可能會在TransformManyBlock中使用yield return。但是我不能將yield return與async一起使用。 – Gidon

回答

1

我明白我的問題是無法使用yield/async在一起。但是重構之後,我擺脫了這種需要,並滿足以下(簡體)版本出來了:

var block = new TransformManyBlock<Stream, Stream>((input) => { 
var archive = new System.IO.Compression.ZipArchive(input, System.IO.Compression.ZipArchiveMode.Read, true); 
foreach (ZipArchiveEntry entry in archive.Entries) 
{ 
    if (string.IsNullOrWhiteSpace(entry.Name)) //is a folder 
     continue; 

    yield return entry.Open(); 

} 

}); 
0

您可以設置爲您解壓縮邏輯的中間塊與predicate linking塊,所以你可以檢查在流存檔或不是,是這樣的:

var buffer = new BufferBlock<Stream>(); 
var unzipper = new TransformManyBlock<Stream, Stream>(input => { /* unzip here */ }); 
var processBlock = new ActionBlock<Stream>(input => { /* process streams here */ }); 

buffer.LinkTo(unzipper, input => /* check is stream a zip archive */); 
unzipper.LinkTo(processBlock); 
buffer.LinkTo(processBlock); 

至於async使用與yield在一起,你可以給一個嘗試在GitHub和​​可用AsyncEnumerable包。