Store must be open for this operation - System.IO.

2019-05-03 22:51发布

I am making use of the System.IO.Packaing.Package class to zip files. It is possible to have multiple instances of my application running at the same time with files being read and saved. When working with small files all seems fine, however when large files are involved if two instances of the application save at the same time I get an exception with the message Store must be open for this operation with the stack trace shown below.

From my understanding when working with the packages for files <10mb the data is stored in some memory stream but when it is >10mb internally that will switch to IsolatedStorage. With that in mind I was able to find that even though these are multiple instances running they all get the same isolated storage location resolved and I believe that is were the problem comes in. I was able to find a hack to force each instance to resolve to a different location using the following code:

var rootDirUserField= typeof(IsolatedStorageFile).GetField("s_RootDirUser", BindingFlags.NonPublic | BindingFlags.Static);
rootDirUserField.SetValue(null, "<unique location in isolated storage>");

Even though that made the problem go away I do not like it one bit. Please help in figuring out how to fix this problem elegantly. On further research I found out that IsolatedStorage is not even meant to be used with multiple threads, which gets me to wonder why it was then an option when dealing with Packages.

   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:

Additionally one can experience issue because to access IsolatedStorage your code must have all the necessary native platform operating system rights and if it doesn’t it will fail to create an IsolatedStorage stream.

Update 2

A hotfix for the .NET Framework 4.5, 4.5.1, and 4.5.2 on Windows 8.1 and Windows Server 2012 R2 was released addressing this issue. Eric White also wrote a new implementation of System.IO.Packaging to not use Isolated Storage and this will actually be added to COREFX. His implementation is available here.

Other problem indicated by Microsoft that could occur with System.IO.Packaging related to this are as follows.

A deadlock may occur when you use large packages on separate threads. System.IO.Packaging uses IsolatedStorage for packages that are larger than 10 megabytes (MB). When two or more threads use large packages, a deadlock may occur, even if the packages are independent. The deadlock involves two threads. One is waiting in IsolatedStorageFile.Lock while the other is waiting in another method of the IsoloatedStorageFile class. This issue is fixed by adding synchronization to System.IO.Packaging to avoid the problem in IsolatedStorageFile. Exceptions may occur when you retrieve PackageProperties from packages that are opened on separate threads, even if the packages are independent. The most common call stacks that arise from this are as follows:

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()

This issue is caused by contention on a shared internal resource, and is resolved by giving each package a copy of that resource.

0条回答
登录 后发表回答