我有一个float
列表要写入文件。下面的代码可以实现,但它是同步的。
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);
}
}
我想异步执行操作,但BinaryWriter
不支持异步操作,这是正常的,因为它每次只写几个字节。但大多数情况下,操作使用文件I / O,我认为它可以而且应该是异步的。
我尝试使用MemoryStream
写入BinaryWriter
,完成后我将MemoryStream
复制到FileStream
CopyToAsync
,但这导致大文件的性能下降(总时间)高达100%。
如何将整个操作转换为异步?
答案 0 :(得分:4)
正常的写操作通常最终会以异步方式完成。操作系统立即接受写入缓存中的写入,并在稍后将其刷新到磁盘。您的应用程序不会被实际的磁盘写入阻止。
当然,如果您要写入可移动驱动器,则通常会禁用写入缓存,并且您的程序将被阻止。
我建议您一次转移一个大块,从而大大减少操作次数。即:
new T[BlockSize]
。new byte[BlockSize * sizeof (T)]
List<T>.CopyTo(index, buffer, 0, buffer.Length)
从列表中复制批次。Buffer.BlockCopy
将数据导入byte[]
。byte[]
写入您的信息流。答案 1 :(得分:1)
您的内存流方法有意义,只需确保批量编写,而不是等待内存流增长到文件的完整大小,然后立即写入。
这样的事应该可以正常工作:
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);
}
}
}
这只是示例代码 - 确保正确处理错误等。
答案 2 :(得分:1)
有时,这些辅助类只是有用的。
试试这个:
List<float> samples = GetSamples();
using (FileStream stream = File.OpenWrite("somefile.bin"))
{
foreach (var sample in samples)
{
await stream.WriteAsync(BitConverter.GetBytes(sample), 0, 4);
}
}