2017-04-24 34 views
6

大きなXML文書をXDocumentオブジェクトに読み込みたい。 XDocument.Load(path, loadOptions)を使用したシンプルな同期アプローチは効果的ですが、大きなファイル(特にネットワークストレージ)をロードする場合、GUIコンテキストで不快な時間をブロックします。XDocumentを非同期でロードする

特に、ネットワーク経由でファイルを読み込む際に、ドキュメントの読み込みの応答性を向上させるために、この非同期バージョンを書きました。

public static async Task<XDocument> LoadAsync(String path, LoadOptions loadOptions = LoadOptions.PreserveWhitespace) 
    { 
     String xml; 

     using (var stream = File.OpenText(path)) 
     { 
      xml = await stream.ReadToEndAsync(); 
     } 

     return XDocument.Parse(xml, loadOptions); 
    } 

ただし、ローカルディスクからロードされた200 MBのXML rawファイルでは、同期バージョンは数秒で完了します。非同期バージョン(32ビットのコンテキストで実行されている)は、代わりOutOfMemoryExceptionをスロー:

at System.Text.StringBuilder.ToString() 
    at System.IO.StreamReader.<ReadToEndAsyncInternal>d__62.MoveNext() 

私はこのためXDocumentによって解析のためにメモリに生のXMLを保持するために使用される一時的な文字列変数である想像します。おそらく同期シナリオでは、XDocument.Load()はソースファイルをストリームすることができ、ファイル全体を保持する単一の巨大なStringを作成する必要はありません。

両方の世界を最大限に活用する方法はありますか? XDocumentを完全非同期I/Oでロードし、大きな一時ストリングを作成する必要はありませんか?

+0

おそらく、あなたは 'XDocument.Load(ストリーム)'使うべきでしょうか? – DavidG

+0

これはどのようにロード操作を非同期にしますか? – Hydrargyrum

+0

それ自体はそうではありませんが、あなたがここに持っている文字列変数とうまくいけばOOM例外を排除します。 – DavidG

答えて

2

まず、タスクは非同期で実行されていません。ビルトインの非同期IOコマンドを使用するか、スレッドプール上のタスクを自分でスピンアップする必要があります。たとえば、

public static async Task<XDocument> LoadAsync 
(String path 
, LoadOptions loadOptions = LoadOptions.PreserveWhitespace 
) 
{ 
    return Task.Run(()=>{ 
    using (var stream = File.OpenText(path)) 
     { 
      return XDocument.Load(stream, loadOptions); 
     } 
    }); 
} 

stream versionを使用すると、一時的な文字列が得られません。

+3

これは私が最後のコメントで概説したものです。したがって、これはスレッドプールスレッドを使用して、暗黙的に必要なI/Oを駆動します.XDocumentがストリームを介して途切れているためです。そして、I/O自体がタスクのワーカースレッドを散発的にブロックします。 これは、フードの下で適切な非同期I/O命令を使用する真のXDocument.LoadAsync()実装が存在しない場合に、実行可能な最高のものです。 私は、明示的にFile.OpenTextを呼び出す利点はありません。XDocument.Load(path)を呼び出すだけでもいいです。 – Hydrargyrum

+0

サーバ上で数十万のXDocumentsを並列に読み込んでいた場合は、真の非同期IOを使用するのではなく、スレッドプールからスレッドを盗むことに心配するかもしれませんが、 ? – bradgonesurfing

+1

おそらくそうではありません。それで、それはおそらく十分に良いと私のコメント。とにかく私は賛成して受け入れた – Hydrargyrum

関連する問題