我想从CSV文件中读取行并使用RX.Net进行一些转换,我想进行批量更新并每250毫秒发送一次更新
public static IEnumerable<string> ReadCSV(string filePath)
{
var reader = new StreamReader(File.OpenRead(filePath));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
yield return line;
}
}
var rows = ReadCSV("filePath").ToObservable();
rows
.Buffer(50)
.Zip(Observable.Interval(
TimeSpan.FromMilliseconds(250)), (res, _) => res)
.Subscribe(lines =>
{
//do something
});
我使用的csv文件的大小约为80mb,但控制台项目的大小为1gb。
这里发生的是Zip正在等待两个序列发出信号。 CSV序列可以非常快速地提供数据,因此它将批处理更新存储在内存中并等待其他序列。
更糟糕的是,即使正在处理所有更新,也不释放内存。如果我删除了Zip,则内存看起来非常好,似乎在处理批处理时正在释放内存(整个应用整个过程大约需要20mb)。
两个问题
有没有办法告诉可观察到的我想暂停读取,直到处理上一个(在我的情况下是缓冲行)。
为什么在处理所有更新后不释放内存,有没有办法避免这种情况?
答案 0 :(得分:0)
我设法找到问题1的解决方案。
rows
.Buffer(50)
.Select(lines =>
{
Thread.Sleep(250);
return lines;
}
.Subscribe(lines =>
{
//do something
});
整个过程是同步的,所以当我执行Thread.Sleep时,可观察对象也会停止读取数据。
但这可能不是一个好答案。
答案 1 :(得分:0)
我无法重新创建您的内存使用问题。我使用了50mb的文件。 但是,我想您可能会遇到麻烦,就是.ToObservable()尽可能快地从IEnumerable中提取数据。
那么为什么不只是通过扩展方法来减慢IEnumerable的速度(从磁盘中拉出数据的速度)呢?
(示例中使用的.Buffer()
的{{1}}运算符在Ix.Net中可用)。
像这样:
IEnumerable
(在C#8中,可以使该方法异步并使用ReadCSC()
.Buffer(50)
.SlowDown(250)
.ToObservable() etc.
...
public static IEnumerable<IList<string>> SlowDown(this IEnumerable<IList<string>> source, int milliSeconds)
{
foreach(var item in source)
{
yield return item;
Thread.Sleep(milliSeconds);
}
}
而不是Task.Delay
,这样就不会阻塞线程。)
这样,以较低的速度从磁盘读取数据。如果能解决您的内存问题,我不知道。