如何有条件地缓冲RX

时间:2019-07-10 13:32:04

标签: c# observable system.reactive

我正在尝试将日志文件作为流加载,因此我可以通过Web获得实时日志尾页。

它应该从日志文件中加载迄今为止的历史行,然后为每个保存的新行触发更新。

为了减少signalR流量,我使用RX缓冲区将它们分成100行,但是在加载初始文件内容时可能会出现问题-可能是10万行。批量加载100太慢了。初始文件内容应作为单个消息发送。

我真正想要的是首先在Observable上发送一个滴答声,其中包含文件的全部内容,然后从那一点起对新行写入进行缓存更新。但是我不确定如何一次获取初始内容,然后从那以后缓冲。

到目前为止我的代码

var watcherSubject = new ReplaySubject<LogTailMessage>()
var watcher = new logFileWatcher(logFileLocation)
new TaskFactory().StartNew(() => watcher.StartFileWatch(data => watcherSubject.OnNext(data), CancellationToken.None));

Stream = watcherSubject
    .Buffer(TimeSpan.FromMilliseconds(500), 100)
    .Where(d => d != null)
    .Replay()
    .RefCount();

更新的解决方案

var initialFileLines = watcher.GetInitialData();

new TaskFactory().StartNew(() => watcher.StartFileWatcher(data => watcherSubject.OnNext(data), _cts.Token));

Stream = watcherSubject.Buffer(TimeSpan.FromMilliseconds(500), 100)
    .StartWith(initialFileLines)
    .Replay()
    .RefCount();

1 个答案:

答案 0 :(得分:0)

使用StartWith

var originalFileLines = new List<LogTailMessage>(); //Initialize with file contents.

Stream = watcherSubject
    .Buffer(TimeSpan.FromMilliseconds(500), 100)
    .Where(d => d != null)
    .StartWith(originalFileLines)
    .Replay()
    .RefCount();

更新:我不确定StartWith为何无法可靠运行。您可以用模拟的示例修改答案吗?

.Concat应该可以工作,尽管我认为这基本上就是StartWith应该做的。:

Stream = Observable.Return(originalFileLines).Concat(
    watcherSubject
        .Buffer(TimeSpan.FromMilliseconds(500), 100)
        .Where(d => d != null)
        .Replay()
        .RefCount()
   );