用例.PublishLast()(以前是Prune)

时间:2011-02-12 05:52:06

标签: c# system.reactive

在我看来,我对RX函数有一个非常好的“感觉” - 我使用了很多这些函数或者可以想象其他函数是如何有用的 - 但是我找不到.Prune函数的位置。我知道这是AsyncSubject的多播,但它在实际场景中如何有用呢?

编辑:理查德说,WebRequest是Prune()的一个很好的候选人。我还是不知道怎么样。让我们举一个例子 - 我想将传入的uri转换为图像:

    public static IObservable<BitmapImage> ToImage(this IObservable<string> source)
    {
        var streams = 
            from wc in source.Select(WebRequest.Create)
            from s in Observable
                .FromAsyncPattern<WebResponse>(wc.BeginGetResponse, 
                    wc.EndGetResponse)()
                .Catch(Observable.Empty<WebResponse>())
            select s.GetResponseStream();
        return streams
            .ObserveOnDispatcher()
            .Select(x =>
                        {
                            var bmp = new BitmapImage();
                            bmp.SetSource(x);
                            return bmp;
                        });
    }

我认为没有必要将.Prune附加到.FromAsyncPattern,因为当你调用FromAsyncPattern()(很热)时,你会“立即”订阅。

3 个答案:

答案 0 :(得分:3)

因为was confirmed on the RX Forum Prune只是一个随从运营商。

如果您的observable有一个值并且您正在发布它,可以用一次调用替换Publish \ Connect .Prune()

根据我的经验,Prune最常见的情况是:

  • 你有一个冷的观察者产生副作用并且只发出一个值
  • 您的观察者有多个订阅者,因此您想让它变热(因为副作用)

论坛中指出的另一个问题是,当你需要在热的可观察量(通常是第一个)上缓存特定值时。然后你使用FromEvent(...)。Take(1).Prune(),任何订阅它的人都会得到相同的保证值。这个不仅仅是“方便”,而且是实现结果的唯一简单方法。

毕竟非常有用!

答案 1 :(得分:2)

最常见的情况是源可观察性很热,可以在订阅之前完成。 AsyncSubject捕获最后一个值,并为任何未来的订户重新发送它。

修改

我必须检查,但我相信FromAsyncPattern在内部使用AsyncSubject,因此实际上已经“修剪过”。

但是,假设您正在使用其他一些没有的热源,Prune的使用完全取决于<{1}} 的生命周期之前订阅至。如果您立即订阅,则无需IObservable。但是,如果Prune在订阅之前存在一段时间,则可能已经完成。

这是我的理解,作为移植了Rx但从未使用IObservable的人。也许你应该在Rx forums上问同样的问题?你有机会被Rx团队的某个人回答。

答案 2 :(得分:1)

当我有多个需要监听任务的UI组件(例如回调)时,我也找到了一个巧妙的用途,默认情况下,冷可观察的Subscribe()会多次启动该任务在跨UI组件共享状态时,这通常不是您想要的。

我知道理查德提到了很多这些要点,但我认为这对于单次运行任务来说是一个非常理想的选择,也可以添加这个例子。

var oTask = Observable.FromAsync(() => Task.Factory.StartNew(() =>
                                                             {
                              Thread.Sleep(1000);
                              Console.WriteLine("Executed Task");
                                                             }));

//Setup the IConnectedObservable
var oTask2 = oTask.PublishLast();

//Subscribe - nothing happens
oTask2.Subscribe(x => { Console.WriteLine("Called from Task 1"); });
oTask2.Subscribe(x => { Console.WriteLine("Called from Task 2"); });

//The one and only time the Task is run
oTask2.Connect();

//Subscribe after the task is already complete - we want the results
Thread.Sleep(5000);
oTask2.Subscribe(x => { Console.WriteLine("Called from Task 3"); });