5

200 MB の Exchange 2007 メールボックスに電子メールがあります。どうしてそんなに大きくなったのか私に聞かないでください。知らない。しかし、それはメールボックスにあり、MIME 形式で送信する必要があります。さらに難しくするには、C# で EWS を使用して MIME 形式で出力する必要があります。

理論的には簡単ですよね?私がしなければならないことは次のとおりです。

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 MB のメールでは、実際の生活はすぐに頭を悩ませます。私のプログラムは、2GB のメモリを使い果たした後、System.OutOfMemoryException で爆発します。スタック トレースは次のことを示しています。

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 MB のメールが BASE64 でエンコードされた XML として RAM に読み込まれています。そして、コールスタック全体でそれをいじるさまざまな自動生成メソッドによって、おそらくRAMに数回保存されている傷に汚れをこすりつけていると思います。

面倒なのは、メソッドから BASE64 でエンコードされた MIME メッセージを取得した後 (小さなメッセージの場合は問題なく動作します)、最初にそれをディスクに書き込み、それを保持しているオブジェクトを解放してメモリを解放することです。FromBase64Transform を使用して BASE64 をディスクから読み取るコードを既に持っています。このような恐ろしいシナリオを防ぎたかったのです。

そうは言っても、XML 応答が RAM で処理されないようにするにはどうすればよいでしょうか? 理想的には、ディスクに書き込んでから順番に読みたいと思います。EWS 用に独自の SOAP クライアントを完全にロールバックする必要なく、これを行う方法はありますか?

Edit2: 前の編集も機能しませんでした。Web サービス クラスを再生成すると壊れました。さて、振り出しに戻ります。

4

0 に答える 0