I tried to write xml file from XElement object with async/await feature. But I realized the XElement.Save() does not operate with async/await.
Maybe the solution can be to use XElement.Save(Stream) with FileStream object...
So, I write some code as below but hard to treat with filestream things.
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**);
}
}
how to do with this approach or is there any other solution?
If you really don't want to block on IO (and hang a ThreadPool thread/your thread), you'll probably need to use a temporary MemoryStream:
using(var ms = new MemoryStream())
using(var fs = new FileStream("myFile", FileMode.Create))
{
xml.Save(ms);
ms.Position = 0;
await ms.CopyToAsync(fs)
}
As of .NET Core 2.0 and .NET Standard 2.1, XElement and XDocument both have SaveAsync() methods. Thus you can now do:
public static async Task SaveAsync(this XElement xml, string filename, SaveOptions options = default, CancellationToken cancellationToken = default)
{
// "await using" introduced in c# 8 / .NET Core 3.0+
await using var stream =
new FileStream(
filename, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096,
useAsync: true);
await xml.SaveAsync(stream, options, cancellationToken);
}
Notes:
In .NET Core 3, XDocument.SaveAsync() (and probably XElement.SaveAsync() also) still contained at least one blocking call. See XDocument.SaveAsync has a blocking call #29464. The issue should be fixed in .NET 5.
According to the docs, the useAsync argument to the FileStream constructor
Specifies whether to use asynchronous I/O or synchronous I/O. However, note that the underlying operating system might not support asynchronous I/O, so when specifying true, the handle might be opened synchronously depending on the platform. When opened asynchronously, the BeginRead(Byte[], Int32, Int32, AsyncCallback, Object) and BeginWrite(Byte[], Int32, Int32, AsyncCallback, Object) methods perform better on large reads or writes, but they might be much slower for small reads or writes. If the application is designed to take advantage of asynchronous I/O, set the useAsync parameter to true. Using asynchronous I/O correctly can speed up applications by as much as a factor of 10, but using it without redesigning the application for asynchronous I/O can decrease performance by as much as a factor of 10.
Since you know you want to write your XElement asynchronously, presumably you have designed your application for asynchronous I/O. However, you might want to benchmark with and without asynchronous IO to confirm you are not harming performance.
Demo fiddle here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With