System.IO.Packaing.Package クラスを使用してファイルを圧縮しています。アプリケーションの複数のインスタンスを同時に実行し、ファイルを読み取って保存することができます。小さなファイルを操作する場合はすべて問題ないように見えますが、大きなファイルが関係している場合、アプリケーションの 2 つのインスタンスが同時に保存されると、以下に示すスタック トレースを使用して、この操作のためにストアを開かなければならないというメッセージで例外が発生します。
私の理解では、10 MB 未満のファイルのパッケージを操作する場合、データはメモリ ストリームに保存されますが、内部で 10 MB を超えると、IsolatedStorage に切り替わります。それを念頭に置いて、これらは複数のインスタンスが実行されているにもかかわらず、それらはすべて同じ分離されたストレージの場所を解決することがわかり、それが問題が発生したと考えています.各インスタンスを強制的に解決するためのハックを見つけることができました.次のコードを使用して別の場所に移動します。
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)
アップデート:
さらに、IsolatedStorage にアクセスするには、コードが必要なネイティブ プラットフォーム オペレーティング システムの権限をすべて持っている必要があり、そうでない場合は、IsolatedStorage ストリームの作成に失敗するため、問題が発生する可能性があります。
更新 2
この問題に対処する Windows 8.1 および Windows Server 2012 R2 上の .NET Framework 4.5、4.5.1、および 4.5.2の修正プログラムがリリースされました。Eric White は、Isolated Storage を使用しない System.IO.Packaging の新しい実装も書きました。これは実際に COREFX に追加される予定です。彼の実装はこちらから入手できます。
これに関連して System.IO.Packaging で発生する可能性がある Microsoft によって示されているその他の問題は次のとおりです。
別のスレッドで大きなパッケージを使用すると、デッドロックが発生する場合があります。System.IO.Packaging は、10 メガバイト (MB) を超えるパッケージに IsolatedStorage を使用します。2 つ以上のスレッドが大きなパッケージを使用すると、パッケージが独立していてもデッドロックが発生することがあります。デッドロックには 2 つのスレッドが関係しています。1 つは IsolatedStorageFile.Lock で待機し、もう 1 つは IsolatedStorageFile クラスの別のメソッドで待機しています。この問題は、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()
この問題は、共有内部リソースの競合によって引き起こされ、各パッケージにそのリソースのコピーを与えることで解決されます。