Нагрузка XDocument используется асинхронно
Я хочу загрузить большие XML-документы в объекты XDocument.
Простой синхронный подход с использованием XDocument.Load(path, loadOptions)
отлично работает, но блокирует в течение неудобно долгого времени в контексте GUI при загрузке больших файлов (особенно из сетевого хранилища).
Я написал эту асинхронную версию с целью улучшения отзывчивости при загрузке документов, особенно при загрузке файлов по сети.
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 МБ XML raw-файл, загруженный с локального диска, синхронная версия завершается через несколько секунд. Асинхронная версия (работает в 32-разрядном контексте), а не выдает OutOfMemoryException
:
at System.Text.StringBuilder.ToString()
at System.IO.StreamReader.<ReadToEndAsyncInternal>d__62.MoveNext()
Я предполагаю, что это из-за временной строковой переменной, используемой для хранения необработанного XML в памяти для синтаксического анализа XDocument
. Предположительно, в синхронном случае XDocument.Load()
способен передавать через исходный файл и никогда не нужно создавать одну огромную строку для хранения всего файла.
есть ли способ получить лучшее обоих миров? Загрузите XDocument
С полностью асинхронным вводом-выводом и без необходимости создания большой временной строки?
2 ответов
прежде всего задача не выполняется асинхронно. Вам нужно будет использовать встроенную команду async 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);
}
});
}
Если вы используете потоковую версию разбора, то вы не получите временную строку.
XDocument.LoadAsync()
доступно в .NET Core 2.0: https://docs.microsoft.com/en-us/dotnet/api/system.xml.linq.xdocument.loadasync?view=netcore-2.0