1

我有一个工作人员,它公开了一个Subject<string>,它可以非常快速地发布日志消息。写入控制台很慢,所以我想最多每 100 毫秒写入一次控制台。任务完成后,我想写出最近发布的字符串,以避免出现Doing work 2312/2400 ...done. (或者即使...done任务花费 <100 毫秒。)

我是响应式扩展的新手,虽然我听说过它们有多棒,但这是我第一次注意到它们可以帮助我的情况。

所以,总而言之,1)不要每 100 毫秒给我一个事件超过一次 2)我需要知道最终事件,无论它何时到达。

我会将我的代码放在下面的答案中,但请提出更好的建议。也许我错过了实现这一目标的标准电话?

4

3 回答 3

4

如果作为事件源的可观察对象在完成时被调用,它实际上比你想象的要简单OnCompleted()。这将自行解决问题:

observable.Sample(TimeSpan.FromMilliseconds(100)).Subscribe(log);

这是因为Sample当它的事件源完成时会最后一次触发。这是一个完整的测试:

var sub = new Subject<string>();
var gen = Observable.Interval(TimeSpan.FromMilliseconds(50)).Select((_,i) => i).Subscribe(i => sub.OnNext(i.ToString()));

sub.Sample(TimeSpan.FromSeconds(1))
   .Subscribe(Console.WriteLine);

Thread.Sleep(3500);
sub.OnCompleted();

即使我睡了 3.5 秒,也会触发 4 个事件,最后一个在我调用时触发OnCompleted()

另一点需要注意的是,如果Worker.GetObservable()实际返回 a是不好的形式Subject<string>- 即使它是在 Worker 类中,它真正应该做的只是返回IObservable<string>接口。这不仅仅是风格,它是关注点的分离并返回所需的最小功能接口。

于 2012-06-01T12:39:51.887 回答
0

这是我想出的代码,似乎可以完成这项工作。我不确定它是多么正确或惯用。

var observable = Worker.GetObservable(); //Actually a Subject<string>
Action<string> log = x => Console.Write("\r" + x);
string latest = "";
using(observable.Subscribe(x => latest = x))
using(observable.Sample(TimeSpan.FromMilliseconds(100)).Subscribe(log))
{
    Worker.DoWorkWithLogs();
    log(latest);
}
Console.WriteLine(" ...done.");
于 2012-06-01T09:55:30.637 回答
0

您可以使用BufferWithTime函数。

于 2012-06-04T12:03:07.090 回答