2015-12-23 20 views
7

私はJSONデータフィードを受け取り、Newtonsoft.Json.JsonConvert.DeserializeObjectコンバータを使用してオブジェクトに変換するC#.NETシステムを使用しています。文字列を読み取るときにOutOfMemoryExceptionが発生する

このプロセスは限りJSON文字列が一定のサイズ(数MB)を下回っているものの、すぐに返されたデータは、(ほとんどの100Mb)大であるように私は、このコードは素晴らしい作品エラーにOutOfMemoryException

を得るよう完璧に動作します小さなデータのために:

// WebClient ------------------------------------------------------------------ 
var _client = new System.Net.WebClient(); 
var _content = _client.DownloadString(_url); 

はなく、最後の行に吹く(DownloadString

私も小さなデータのために働くこれに変更しようとしたが、それはまだReadToEndラインに吹いたときデータのサイズが大きくなりました。

StringBuilder _stringBuilder = new StringBuilder(); 
using (var _response = (System.Net.HttpWebResponse)_request.GetResponse()) 
{ 
    using (System.IO.Stream _dataStream = _response.GetResponseStream()) 
    { 
     using (System.IO.StreamReader _streamReader = new System.IO.StreamReader(_dataStream)) 
     { 
      while (!streamReader.EndOfStream) 
      { 
       char[] _buffer = new char[4096]; 
       _streamReader.ReadBlock(_buffer, 0, _buffer.Length); 
       var _bufferString = new String(_buffer); 
       _stringBuilder.Append(_bufferString); 
      } 
     } 
    } 
} 

をしかし、それは、ここで次の行に着いたとき、それはOutOfMemoryExceptionエラーで爆破:

var _results = Newtonsoft.Json.JsonConvert.DeserializeObject<List<MyObject>>(_stringBuilder.ToString()); 

それは好きではなかった

using (var _response = (System.Net.HttpWebResponse)_request.GetResponse()) 
{ 
    using (System.IO.Stream _dataStream = _response.GetResponseStream()) 
    { 
     using (System.IO.StreamReader _streamReader = new System.IO.StreamReader(_dataStream)) 
     { 
      string _responseFromServer = _streamReader.ReadToEnd(); 
     } 
    } 
} 

は、最後に私が働いている、これを試してみましたToString()メソッド。

それはまた、完全な誤りがある

string _convertedString = _stringBuilder.ToString(); 

のようなシンプルなラインで墜落:

タイプの例外「System.OutOfMemoryExceptionに」 がmscorlib.dllで発生したが、中に処理されませんでしたユーザコード

マシンは16Gbのメモリを搭載した64ビットウィンドウを実行しています。

私のオプションは何ですか?

私が欲しいのは、IQueryable<MyObject>から(非常に大きい)JSON文字列です。

+1

チェックアウト、この質問に対する答えを、http://stackoverflow.com/questions/27315521/system-outofmemoryexception-with-json-net-with-listobject、 – dbugger

+2

OutOfMemoryExceptionは、バッファリング、GDIオブジェクトなどのさまざまな理由で発生することがあります。例外の呼び出しスタックは、発生した場所を示しますが、実際の原因は非効率なコードです。 * WHY * StreamReaderでデータを読み取ることができるときにStringBuilderを使用していますか?あなたがやっていることは、 'streamReaderより優れている(またはより効率的ではありません)。ReadToEnd() ' –

+0

@ PanagiotisKanavos - これは私がこれをプロセスを表示するためだけに動作させようと試みた様々な方法です。メモリエラーがなくてもStreamReaderの値をデシリアライザに渡す方法があれば、私は知りたいと思うでしょう。 – DeclanMcD

答えて

7

あなたのコードは、大きなレスポンス(文字列レスポンス自体のメモリ、StringBuilderの内部バッファ、すべての中間テンポラリ文字列のサイズ、および最終的なテンポラリ文字列のサイズ)の少なくとも4倍のメモリを必要とすることを本質的にエミュレートします。文字列)。

ストリームからJsonTextReaderで直接デシリアライズすることで、この問題を回避できます。 documentation sampleからコピー:

using (var json= new JsonTextReader(streamReader)) 
{ 
    JsonSerializer serializer = new JsonSerializer(); 
    return (List<MyObject>)serializer.Deserialize(json, typeof(List<MyObject>)); 
} 

O

+0

完璧!初めての扱い - コードのマイナーな変更 - 単語ファイルをjsonTextReaderに変更 – DeclanMcD

関連する問題