简体   繁体   English

在异步代码中使用BinaryWriter或BinaryReader

[英]Using BinaryWriter or BinaryReader in async code

I have a list of float to write to a file. 我有一个要写入文件的float列表。 The code below does the thing but it is synchronous. 下面的代码做了事情,但它是同步的。

List<float> samples = GetSamples();

using (FileStream stream = File.OpenWrite("somefile.bin"))
using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.Default, true))
{
    foreach (var sample in samples)
    {
        binaryWriter.Write(sample);
    }
}

I want to do the operation asynchronously but the BinaryWriter does not support async operations, which is normal since it just only writes a few bytes each time. 我想异步执行操作,但BinaryWriter不支持异步操作,这是正常的,因为它每次只写几个字节。 But most of the time the operation uses file I/O and I think it can and should be asynchronous. 但大多数情况下,操作使用文件I / O,我认为它可以而且应该是异步的。

I tried to write to a MemoryStream with the BinaryWriter and when that finished I copied the MemoryStream to the FileStream with CopyToAsync , however this caused a performance degradation (total time) up to 100% with big files. 我尝试使用BinaryWriter写入MemoryStream ,完成后我使用CopyToAsyncMemoryStream复制到FileStream ,但是这会导致大文件的性能下降(总时间)高达100%。

How can I convert the whole operation to asynchronous? 如何将整个操作转换为异步?

Normal write operations usually end up being completed asynchronously anyway. 正常的写操作通常最终会以异步方式完成。 The OS accepts writes immediately into the write cache, and flushes it to disk at some later time. 操作系统立即接受写入缓存中的写入,并在稍后将其刷新到磁盘。 Your application isn't blocked by the actual disk writes. 实际的磁盘写入不会阻止您的应用程序。

Of course, if you are writing to a removable drive then write cache is typically disabled and your program will be blocked. 当然,如果您要写入可移动驱动器,则通常会禁用写入缓存,并且您的程序将被阻止。


I will recommend that you can dramatically reduce the number of operations by transferring a large block at a time. 我建议您可以通过一次传输大块来大幅减少操作数量。 To wit: 以机智:

  1. Allocate a new T[BlockSize] of your desired block size. 分配所需块大小的new T[BlockSize]
  2. Allocate a new byte[BlockSize * sizeof (T)] 分配一个new byte[BlockSize * sizeof (T)]
  3. Use List<T>.CopyTo(index, buffer, 0, buffer.Length) to copy a batch out of the list. 使用List<T>.CopyTo(index, buffer, 0, buffer.Length)将批处理复制出列表。
  4. Use Buffer.BlockCopy to get the data into the byte[] . 使用Buffer.BlockCopy将数据输入byte[]
  5. Write the byte[] to your stream in a single operation. 只需一次操作即可将byte[]写入流中。
  6. Repeat 3-5 until you reach the end of the list. 重复3-5,直到到达列表的末尾。 Careful about the final batch, which may be a partial block. 小心最后一批,这可能是一个部分块。

Your memory stream approach makes sense, just make sure to write in batches rather than waiting for the memory stream to grow to the full size of the file and then writing it all at once. 您的内存流方法是有意义的,只需确保批量写入,而不是等待内存流增长到文件的完整大小,然后一次写入所有内容。

Something like this should work fine: 像这样的东西应该工作正常:

var data = new float[10 * 1024];
var helperBuffer = new byte[4096];

using (var fs = File.Create(@"D:\Temp.bin"))
using (var ms = new MemoryStream(4096))
using (var bw = new BinaryWriter(ms))
{
  var iteration = 0;

  foreach (var sample in data)
  {
    bw.Write(sample);

    iteration++;

    if (iteration == 1024)
    {
      iteration = 0;
      ms.Position = 0;

      ms.Read(helperBuffer, 0, 1024 * 4);
      await fs.WriteAsync(helperBuffer, 0, 1024 * 4).ConfigureAwait(false);
    }
  }
}

This is just sample code - make sure to handle errors properly etc. 这只是示例代码 - 确保正确处理错误等。

Sometimes, these helper classes are anything but helpful. 有时,这些辅助类只是有用的。

Try this: 尝试这个:

List<float> samples = GetSamples();

using (FileStream stream = File.OpenWrite("somefile.bin"))
{
    foreach (var sample in samples)
    {
        await stream.WriteAsync(BitConverter.GetBytes(sample), 0, 4);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用BinaryReader / BinaryWriter建立聊天 - Using BinaryReader/BinaryWriter to build a chat 具有简单BinaryWriter和BinaryReader的EndOfStreamException - EndOfStreamException with simple BinaryWriter and BinaryReader NetworkStream上的BinaryReader和BinaryWriter - BinaryReader and BinaryWriter over NetworkStream 我们是否需要在使用块中关闭C#BinaryWriter或BinaryReader? - Do we need to close a C# BinaryWriter or BinaryReader in a using block? 用于动态短数组的BinaryReader和BinaryWriter - BinaryReader and BinaryWriter for dynamic short array 在同一个CryptoStream上使用BinaryReader和BinaryWriter时,如何避免超时? - How do I avoid timeout when using BinaryReader and BinaryWriter on the same CryptoStream? 使用 BinaryReader/BinaryWriter 从/向同一行读取和写入 - Read and write from/to the same line with BinaryReader/BinaryWriter 通过NetworkStream BinaryReader / BinaryWriter计算TcpClient传输的字节数 - Count bytes transmitted by TcpClient via NetworkStream BinaryReader/BinaryWriter 如何在BinaryReader和BinaryWriter(.NET,C#)中使用NodaTime? - How to Use NodaTime with BinaryReader & BinaryWriter (.NET, C#)? C ++中是否有BinaryReader来读取从C#中的BinaryWriter写入的数据? - Is there a BinaryReader in C++ to read data written from a BinaryWriter in C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM