我正在使用 System.IO.Packaing.Package 类来压缩文件。我的应用程序的多个实例可以同时运行,并读取和保存文件。当处理小文件时,一切似乎都很好,但是当涉及大文件时,如果应用程序的两个实例同时保存,我会收到一个异常,消息“必须为该操作打开存储”,堆栈跟踪如下所示。
根据我的理解,当使用 10mb 时,将切换到独立存储。考虑到这一点,我发现即使这些是多个实例在运行,它们都得到了相同的独立存储位置的解决,我相信这就是问题所在。我能够找到一个黑客来强制每个实例解决使用以下代码到不同的位置:
var rootDirUserField= typeof(IsolatedStorageFile).GetField("s_RootDirUser", BindingFlags.NonPublic | BindingFlags.Static);
rootDirUserField.SetValue(null, "<unique location in isolated storage>");
尽管这让问题消失了,但我一点也不喜欢它。请帮助弄清楚如何优雅地解决这个问题。经过进一步的研究,我发现isolatedStorage甚至不适合与多线程一起使用,这让我想知道为什么它是处理包时的一个选项。
at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, IsolatedStorageFile isf)
at MS.Internal.IO.Packaging.PackagingUtilities.SafeIsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, ReliableIsolatedStorageFileFolder folder)
at MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32 retryCount, String& fileName)
at MS.Internal.IO.Packaging.SparseMemoryStream.EnsureIsolatedStoreStream()
at MS.Internal.IO.Packaging.SparseMemoryStream.SwitchModeIfNecessary()
at MS.Internal.IO.Packaging.SparseMemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Zip.ZipIOFileItemStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
Update:
此外,人们可能会遇到问题,因为要访问isolatedStorage,您的代码必须拥有所有必要的本机平台操作系统权限,如果没有,它将无法创建IsolatedStorage流。
Update 2
A hotfix https://support.microsoft.com/en-us/kb/2996566针对 Windows 8.1 和 Windows Server 2012 R2 上的 .NET Framework 4.5、4.5.1 和 4.5.2 已发布,以解决此问题。 Eric White 还编写了 System.IO.Packaging 的新实现,以不使用独立存储,这实际上将添加到 COREFX 中。他的实现是可用的here https://github.com/OfficeDev/Open-XML-SDK/tree/vNext/System.IO.Packaging.
Microsoft 指出的与此相关的 System.IO.Packaging 可能出现的其他问题如下。
当您在单独的线程上使用大型包时,可能会发生死锁。 System.IO.Packaging 对大于 10 兆字节 (MB) 的包使用isolatedStorage。当两个或多个线程使用大包时,即使包是独立的,也可能会发生死锁。死锁涉及两个线程。一个在IsolatedStorageFile.Lock 中等待,而另一个在IsoloatedStorageFile 类的另一个方法中等待。通过向 System.IO.Packaging 添加同步以避免isolatedStorageFile 中的问题,已解决此问题。
当您从在单独线程上打开的包检索 PackageProperties 时,即使这些包是独立的,也可能会发生异常。由此产生的最常见的调用堆栈如下:
System.Xml.XmlException: Unrecognized root element in Core Properties part. Line 2, position 2. at
MS.Internal.IO.Packaging.PartBasedPackageProperties.ParseCorePropertyPart(PackagePart part) at
System.IO.Packaging.Package.get_PackageProperties()
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: id at
MS.Internal.IO.Packaging.PartBasedPackageProperties.ParseCorePropertyPart(PackagePart part) at
System.IO.Packaging.Package.get_PackageProperties()
此问题是由共享内部资源的争用引起的,可通过为每个包提供该资源的副本来解决。