XElement для сохранения файла с помощью async/await в С#

Я попытался написать xml-файл из объекта XElement с функцией async/await. Но я понял, что XElement.Save() не работает с async/await.

Возможно, решение может заключаться в использовании XElement.Save(Stream) с объектом FileStream...

Итак, я пишу код, как показано ниже, но его трудно обрабатывать с помощью файлового потока.

public async Task SaveAsync(XElement xml, string filename)
{
    using (var fs = new FileStream(filename, FileMode.Create))
    {
        xml.Save(fs);
        await fs.WriteAsync(**please_help_me**);
    }
}

как быть с этим подходом или есть какое-то другое решение?


person Youngjae    schedule 18.09.2012    source источник


Ответы (3)


XElement не имеет методов для асинхронной записи, поэтому любые вызовы, которые вы делаете с ним, будут синхронными. Если вам нужно сделать этот метод асинхронным (например, это происходит в потоке пользовательского интерфейса, и вы хотите сделать это в фоновом потоке, чтобы приложение не «зависало» во время сохранения XML), вы может захотеть начать новую задачу и сохранить ее в фоновом режиме.

public async Task SaveAsync(XElement xml, string filename)
{
    await Task.Factory.StartNew(delegate
    {
        using (var fs = new FileStream("myFile", FileMode.Create))
        {
            xml.Save(fs);
        }
    });
}
person carlosfigueira    schedule 18.09.2012
comment
Да, я знаю. поэтому я пытаюсь альтернативно использовать FileStream.WriteAsync с методом XElement.Save. этот подход также блокирует пользовательский интерфейс? - person Youngjae; 18.09.2012
comment
Вызов XElement.Save является синхронным, поэтому он будет заблокирован. Я обновил свой ответ примером того, как сохранить в фоновом потоке. - person carlosfigueira; 18.09.2012
comment
это можно написать одной строкой: await Task.Factory.StartNew(() => xml.Save(filename)); - person Adam; 18.09.2012
comment
@codesparkle Давай поиграем в код-гольф: await Task.Run(() => xml.Save(filename));. - person svick; 18.09.2012
comment
@svick никогда не использовал Tasks, мне это не приходило в голову;) Кажется, пришло время наверстать упущенное в .NET4.5. - person Adam; 19.09.2012

Если вы действительно не хотите блокировать ввод-вывод (и повесить поток ThreadPool/ваш поток), вам, вероятно, потребуется использовать временный MemoryStream:

using(var ms = new MemoryStream())
using(var fs = new FileStream("myFile", FileMode.Create))
{
    xml.Save(ms);
    ms.Position = 0;
    await ms.CopyToAsync(fs)
}
person spender    schedule 18.09.2012