写入文件时Json.net异步

Boa*_*ler 9 c# json.net c#-5.0 windows-runtime winrt-async

Json.net具有将对象转换为json的异步函数,如:

jsn = await JsonConvert.DeserializeObjectAsync<T>
Run Code Online (Sandbox Code Playgroud)

但是当我想将对象写入json文件时,我最好直接使用文件Stream.

所以我认为它应该是这样的:

 var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite);

    using (IOutputStream outputStream = fileStream.GetOutputStreamAt(0))
    {
        using (StreamWriter sw = new StreamWriter(fileStream.AsStreamForWrite()))
        {
            using (JsonWriter jw = new JsonTextWriter(sw))
            {
                jw.Formatting = Formatting.Indented;

                JsonSerializer serializer = new JsonSerializer();
                serializer.Serialize(jw, obj);
            }
        }
Run Code Online (Sandbox Code Playgroud)

但是在JsonSerzializer对象上我找不到异步方法.另外我认为IO操作不应该放在自己的线程中.

推荐的方法是什么?

svi*_*ick 15

Json.NET并不真正支持异步去/序列化.异步方法JsonConvert只是在另一个线程上运行它们的同步方法的包装器(这正是库不应该做的).

我认为这里最好的方法是在另一个线程上运行文件访问代码.这不会给你带来的全部优势async(它会浪费一个线程),但它不会阻止UI线程.


Man*_*gor 8

另请参阅此代码,该代码使用正确的异步方式(例如,它不会创建巨大的字节数组以避免LOH内存分配,它不会等待IO操作完成).

// create this in the constructor, stream manages can be reused
// see details in this answer https://stackoverflow.com/a/42599288/185498
var streamManager = new RecyclableMemoryStreamManager();

using (var file = File.Open(destination, FileMode.Create))
{
    using (var memoryStream = streamManager.GetStream()) // RecyclableMemoryStream will be returned, it inherits MemoryStream, however prevents data allocation into the LOH
    {
        using (var writer = new StreamWriter(memoryStream))
        {
            var serializer = JsonSerializer.CreateDefault();

            serializer.Serialize(writer, data);

            await writer.FlushAsync().ConfigureAwait(false);

            memoryStream.Seek(0, SeekOrigin.Begin);

            await memoryStream.CopyToAsync(file).ConfigureAwait(false);
        }
    }

    await file.FlushAsync().ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

整个文件:https://github.com/imanushin/AsyncIOComparison/blob/0e2527d5c00c2465e8fd2617ed8bcb1abb529436/IntermediateData/FileNames.cs

  • 你假装你的代码“不会创建巨大的字节数组来避免 LOH 内存分配”,但实际上 `MemoryStream` 在内部就是这样做的,它将所有内容缓存在一个单字节数组中,该数组在需要时增长。 (3认同)
  • 恕我直言,考虑到接受的答案完全忽略了用户尝试执行IO的事实,因此没有给出真实的示例,因此此答案比接受的答案更好。 (2认同)
  • @ManushinIgor好的,即使它仍然需要将完整的数据缓存在内存中,也更好。但是请注意,指向“整个文件”的链接仍具有旧代码。 (2认同)