Using WordprocessingDocument error: Unable to create mutex

1

I'm using this simple pattern to create a docx file in an ASP.NET app:

var outputFileName = "creating some file name here...";
var outputFile = string.Format("~/App_Data/files/{0}.docx", outputFileName);

// creating a file stream to write to
var outputStream = new FileStream(HttpContext.Current.Server.MapPath(outputFile), FileMode.OpenOrCreate);

// creating the default template
using (var sr = new StreamReader(HttpContext.Current.Server.MapPath("~/some-template.docx"), Encoding.UTF8)) {
    var l = (int)sr.BaseStream.Length;
    var buffer = new byte[l];
    sr.BaseStream.Read(buffer, 0, l);
    outputStream.Write(buffer, 0, l);
}

// creating the document parts
using (WordprocessingDocument docx = WordprocessingDocument.Open(outputStream, true)) {
    // adding parts here...

    // adding a large amount of data in an iterator 
    foreach(var item in someList) {
        // adding some parts...
        outputStream.Flush();
    }

    docx.Close();
}

outputStream.Flush();
outputStream.Close();
outputStream.Dispose();

I have to say, the data I'm working on, is about 100,000 records from DB.

In local, it works just fine; in production server (win 2012 R2), it works fine for small files; but in large files (when there is too many records to write to file) I get this error:

Unable to create mutex. (Exception from HRESULT: 0x80131464)

And here is the stack trace:

at System.IO.IsolatedStorage.IsolatedStorageFile.Open(String infoFile, String syncName) at System.IO.IsolatedStorage.IsolatedStorageFile.Lock(Boolean& locked) 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.SwitchModeIfNecessary() at MS.Internal.IO.Packaging.SparseMemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count) at MS.Internal.IO.Packaging.CompressEmulationStream.Write(Byte[] buffer, Int32 offset, Int32 count) at MS.Internal.IO.Packaging.CompressStream.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) at System.Xml.XmlUtf8RawTextWriter.FlushBuffer() at System.Xml.XmlUtf8RawTextWriter.RawText(Char* pSrcBegin, Char* pSrcEnd) at System.Xml.XmlUtf8RawTextWriter.RawText(String s) at System.Xml.XmlUtf8RawTextWriter.WriteStartAttribute(String prefix, String localName, String ns) at System.Xml.XmlWellFormedWriter.WriteStartAttribute(String prefix, String localName, String namespaceName) at DocumentFormat.OpenXml.OpenXmlElement.WriteAttributesTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlCompositeElement.WriteContentTo(XmlWriter w) at DocumentFormat.OpenXml.OpenXmlPartRootElement.WriteTo(XmlWriter xmlWriter) at DocumentFormat.OpenXml.OpenXmlPartRootElement.SaveToPart(OpenXmlPart openXmlPart) at DocumentFormat.OpenXml.OpenXmlPartRootElement.Save() at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContents() at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose(Boolean disposing) at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose() at MyClass.GetDocx()

The question is: While I'm writing the file to my own App_Data folder, why it's going to IsolatedStorage? How can I prevent that?

c#
.net
openxml
docx
openxml-sdk
asked on Stack Overflow Feb 23, 2015 by ravy amiry • edited Jul 30, 2015 by ravy amiry

1 Answer

2

In the stack trace you can find SparseMemoryStream class. This class under the hood uses either Memory Stream or Isolated Storage. It depends on 2 parameters called Low Water Mark and High Water Mark. If memory consumption is > than High Water Mark then Isolated Storage is used. As you observed it becomes a problem in the case of server side applications running on IIS. Unfortunately, the problem is that values of these parameters are hard coded in the CompressStream class. In other words it is by design.

 private const long _lowWaterMark = 0x19000; // we definately would like to keep everythuing under 100 KB in memory  
 private const long _highWaterMark = 0xA00000; // we would like to keep everything over 10 MB on disk

The author of EPPlus library had the similar problem and it seems to me that the solution was to use non-Microsoft packaging library.

I don't know openxml-sdk but maybe it is possible to replace a default Microsoft packaging solution with something else.


User contributions licensed under CC BY-SA 3.0