[英]Observable.Using and async streams getting corrupted data
我有一股流,其目的是要計算一組.zip文件中內容的簡單“校驗和” 。
為此,我設置了一個可觀察到的:
ZipArchive
讀取) 為了說明這一點,我創建了以下示例:
注意使用AsyncContext.Run
( https://stackoverflow.com/a/9212343/1025407 )來使Main
方法等待GetChecksum
因為它是控制台應用程序
namespace DisposePoC
{
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reactive.Linq;
using Nito.AsyncEx;
using System.Linq;
using System.Threading.Tasks;
class Program
{
private static void Main()
{
AsyncContext.Run(GetChecksums);
}
private static async Task<IList<byte>> GetChecksums()
{
var bytes = Directory.EnumerateFiles("FolderWithZips")
.ToObservable()
.SelectMany(path => Observable.Using(() => CreateZipArchive(path), archive => archive.Entries.ToObservable()))
.SelectMany(entry => Observable.Using(entry.Open, stream => Observable.FromAsync(() => CalculateChecksum(stream, entry.Length))));
return await bytes.ToList();
}
private static ZipArchive CreateZipArchive(string path)
{
return new ZipArchive(new FileStream(path, FileMode.Open, FileAccess.Read));
}
private static async Task<byte> CalculateChecksum(Stream stream, long entryLength)
{
var bytes = await GetBytesFromStream(stream, entryLength);
return bytes.Aggregate((b1, b2) => (byte) (b1 ^ b2));
}
private static async Task<byte[]> GetBytesFromStream(Stream stream, long entryLength)
{
byte[] bytes = new byte[entryLength];
await stream.ReadAsync(bytes, 0, (int)entryLength);
return bytes;
}
}
}
運行該應用程序,我會遇到各種錯誤:
'System.IO.InvalidDataException':本地文件頭已損壞。 'System.NotSupportedException':流不支持讀取。 'System.ObjectDisposedException':無法訪問已處置的對象。 'System.IO.InvalidDataException':塊長度與其補碼不匹配。
我究竟做錯了什么?
可觀察性本身是否存在問題,還是因為ZipArchive
並非線程安全的? 如果不是,如何使代碼正常工作?
Rx可能不是最合適的選擇。 老實說,您甚至可以在沒有異步的情況下進行操作。
Directory.EnumerateFiles("FolderWithZips")
.AsParallel()
.Select(folder => CalculateChecksum(folder))
.ToList()
您的問題似乎沒有任何“ Rx”。
如果將整個事情修改為命令集,那么它會很好地工作
private static async Task<IList<byte>> GetChecksums()
{
var bytes = new List<byte>();
foreach (var path in Directory.EnumerateFiles("FolderWithZips"))
{
using (var archive = CreateZipArchive(path))
{
foreach (var entry in archive.Entries)
{
using (var stream = entry.Open())
{
var checksum = await CalculateChecksum(stream, entry.Length);
bytes.Add(checksum);
}
}
}
}
return bytes;
}
因此,我想您會遇到一系列競爭條件(並發)和/或亂序處理問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.