EWS Запрос GetItem + IncludeMimeContent + Огромная Почта = OutOfMemoryException - PullRequest
5 голосов
/ 19 мая 2011

У меня есть электронная почта в почтовом ящике Exchange 2007 размером 200 МБ. Не спрашивайте меня, как это стало таким большим; Я не знаю. Но он находится в почтовом ящике и должен выходить в формате MIME. Чтобы сделать его более сложным, ему нужно выйти в формате MIME, используя EWS в C #.

Теоретически, это кусок пирога, верно? Все, что мне нужно сделать, это:

GetItemType getItemRequest = new GetItemType {
    ItemIds = new ItemIdType[] { sItemId },
    ItemShape = new ItemResponseShapeType {
        BaseShape = DefaultShapeNamesType.IdOnly,
        IncludeMimeContent = true,
        IncludeMimeContentSpecified = true,
        BodyType = BodyTypeResponseType.Best,
        BodyTypeSpecified = true
    }
};

... а затем отправьте его:

GetItemResponseType getItemResponse = oService.GetItem(getItemRequest);

Но с 200 МБ почты реальная жизнь поражает вас очень быстро. Моя программа взрывается с System.OutOfMemoryException после того, как она съела 2 ГБ памяти. Трассировка стека указывает мне:

System.Text.StringBuilder.ToString()
System.Xml.XmlTextReaderImpl.ParseText()
System.Xml.XmlTextReaderImpl.ParseElementContent()
System.Xml.XmlTextReaderImpl.Read()
System.Xml.XmlTextReader.Read()
System.Xml.XmlReader.ReadStartElement()
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read75_MimeContentType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read139_MessageType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read302_ArrayOfRealItemsType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read310_ItemInfoResponseMessageType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read315_ArrayOfResponseMessagesType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read331_GetItemResponseType(Boolean isNullable, Boolean checkType)
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExchangeServiceBinding.Read429_GetItemResponse()
Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer125.Deserialize(XmlSerializationReader reader)
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
MyAwesomeApp.ExchangeService.ExchangeServiceBinding.GetItem(GetItemType GetItem1)

И, конечно же, моя 200-мегабайтная почта в виде XML-кода, закодированного в BASE64, читается в ОЗУ. И я полагаю, что грязь в рану, которую она, вероятно, несколько раз хранит в ОЗУ, генерируется различными автоматически сгенерированными методами, которые связываются с ней по всему стеку вызовов.

Раздражает то, что после того, как я получаю обратно сообщение MIME в кодировке BASE64 из метода (работает нормально для небольших сообщений), первое, что я делаю, - это записываю его на диск и освобождаю объект, который его удерживает, чтобы освободить память. У меня уже есть код, который использует FromBase64Transform для декодирования BASE64 во время чтения с диска. Я хотел предотвратить такой ужасный сценарий, как этот.

При этом, что я могу сделать, чтобы избежать обработки XML-ответа в ОЗУ? В идеале я хотел бы записать его на диск, а затем прочитать его последовательно. Любая идея, как я могу сделать это без необходимости полностью развернуть мой собственный клиент SOAP для EWS?

Edit2: предыдущее редактирование также не работало. Регенерирующий класс веб-сервиса сломал это. Ну что ж, вернемся к исходной точке.

...