在我目前的代码中,我有一个这样的方法来读取设备中的数据(伪代码):
public async Task<string> ReadAllDataFromDevice()
{
var buffer = "";
using (var device = new Device())
{
while(device.HasMoreData)
{
buffer += await device.ReadLineAsync();
}
}
return buffer;
}
然后我想通过网络将所有数据发送给某个接收器。数据量可能非常大。很明显,上述设计的内存效率不高,因为它需要在我开始将数据发送到网络套接字之前读取所有数据。
所以我想要的是一个返回流的函数。像这样:
public async Task<Stream> ReadAllDataFromDevice()
{
var stream = new MemoryStream();
using (var device = new Device())
using (var streamWriter = new StreamWriter(stream, new UTF8Encoding(), 512, true))
{
while(device.HasMoreData)
{
var line = await device.ReadLineAsync();
await streamWriter.WriteLineAsync(line);
}
await streamWriter.FlushAsync();
}
return stream;
}
这会返回一个流,但它显然无法解决我的问题,因为只有在从设备读取所有数据后才返回流。
所以我想出了这个:
public Stream ReadAllDataFromDevice()
{
var stream = new MemoryStream();
Task.Run(async () => {
using (var device = new Device())
using (var streamWriter = new StreamWriter(stream, new UTF8Encoding(), 512, true))
{
while(device.HasMoreData)
{
var line = await device.ReadLineAsync();
await streamWriter.WriteLineAsync(line);
}
await streamWriter.FlushAsync();
}
});
return stream;
}
这是一个好设计吗?我特别关注线程安全性,lambda中使用的流对象的生命周期以及异常处理。
或者这种问题有更好的模式吗?
修改
实际上我只想出了另一种看起来更干净的设计。我没有让ReadAllDataFromDevice()
函数返回流,而是让数据的使用者提供流,如下所示:
public async Task ReadAllDataFromDevice(Stream stream)
{
using (var device = new Device())
using (var streamWriter = new StreamWriter(stream, new UTF8Encoding(), 512, true))
{
while(device.HasMoreData)
{
var line = await device.ReadLineAsync();
await streamWriter.WriteLineAsync(line);
}
await streamWriter.FlushAsync();
}
}
答案 0 :(得分:1)
这是我现在使用的设计:
public async Task ReadAllDataFromDevice(Func<Stream, Task> readCallback)
{
using (var device = new Device())
{
await device.Initialize();
using (var stream = new DeviceStream(device))
{
await readCallback(stream);
}
}
}
逐行设备访问封装在自定义DeviceStream
类中(此处未显示)。
数据的消费者看起来像这样:
await ReadAllDataFromDevice(async stream => {
using (var streamReader(stream))
{
var data = await streamReader.ReadToEndAsync();
// do something with data
}
});