【发布时间】:2017-05-23 01:20:03
【问题描述】:
我正在阅读一个 zip 文件的内容并尝试提取它们。
var allZipEntries = ZipFile.Open(zipFileFullPath, ZipArchiveMode.Read).Entries;
现在,如果我提取 using Foreach 循环,则可以正常工作。缺点是它相当于 zip.extract 方法,当打算提取所有文件时我没有任何优势。
foreach (var currentEntry in allZipEntries)
{
if (currentEntry.FullName.Equals(currentEntry.Name))
{
currentEntry.ExtractToFile($"{tempPath}\\{currentEntry.Name}");
}
else
{
var subDirectoryPath = Path.Combine(tempPath, Path.GetDirectoryName(currentEntry.FullName));
Directory.CreateDirectory(subDirectoryPath);
currentEntry.ExtractToFile($"{subDirectoryPath}\\{currentEntry.Name}");
}
}
现在要利用 TPL,尝试使用 Parallel.forEach,但这会引发以下异常:
System.IO.Compression.dll 中出现“System.IO.InvalidDataException”类型的异常,但未在用户代码中处理
附加信息:本地文件头已损坏。
Parallel.ForEach(allZipEntries, currentEntry =>
{
if (currentEntry.FullName.Equals(currentEntry.Name))
{
currentEntry.ExtractToFile($"{tempPath}\\{currentEntry.Name}");
}
else
{
var subDirectoryPath = Path.Combine(tempPath, Path.GetDirectoryName(currentEntry.FullName));
Directory.CreateDirectory(subDirectoryPath);
currentEntry.ExtractToFile($"{subDirectoryPath}\\{currentEntry.Name}");
}
});
为了避免这种情况,我可以使用 lock ,但这违背了整个目的。
Parallel.ForEach(allZipEntries, currentEntry =>
{
lock (thisLock)
{
if (currentEntry.FullName.Equals(currentEntry.Name))
{
currentEntry.ExtractToFile($"{tempPath}\\{currentEntry.Name}");
}
else
{
var subDirectoryPath = Path.Combine(tempPath, Path.GetDirectoryName(currentEntry.FullName));
Directory.CreateDirectory(subDirectoryPath);
currentEntry.ExtractToFile($"{subDirectoryPath}\\{currentEntry.Name}");
}
}
});
还有其他或更好的方法来提取文件吗?
【问题讨论】:
-
问题是您已经阅读了一个 zip 文件,并且您正在尝试并行提取它。您可以做的是将其读入内存,然后并行提取,但是在行的末尾,当 windows 碰到磁盘时,您的写入 IO 仍然是非并行的。
标签: c# foreach zip task-parallel-library parallel.foreach