Вариант использования для .PublishLast () (ранее Prune) - PullRequest
3 голосов
/ 12 февраля 2011

По моему мнению, я достаточно хорошо "чувствую" функции RX - я использую многие из них или могу представить, как другие могут быть полезны - но я не могу найти место для функции .Prune. Я знаю, что это Multicast to 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 ]

3 голосов
/ 14 февраля 2011

Как это было подтверждено на RX Forum Prune - просто оператор по сбору сообщений.

Если ваша наблюдаемая имеет одно значение, и вы публикуете его, можете заменить Publish \ Connect одним вызовом .Prune ()

Итак, по моему опыту, наиболее распространенный сценарий для Prune:

  • У вас наблюдаемая простуда, которая вызывает побочные эффекты и излучает только одно значение
  • У вас есть более одного подписчика на это наблюдаемое, поэтому вы хотите сделать его горячим (из-за побочных эффектов)

Другой, указанный на форуме, случай, когда вам необходимо кэшировать определенное значение в горячей наблюдаемой (обычно первой). Затем вы используете FromEvent (...). Take (1) .Prune (), и любой, кто подпишется на это, получит такое же гарантированное значение. Это не просто «удобство», но практически единственный простой способ достичь результата.

Довольно полезно, в конце концов!

2 голосов
/ 12 февраля 2011

Наиболее распространенный сценарий - когда наблюдаемый источник горячий и может завершиться до того, как вы подпишетесь на него.AsyncSubject захватывает последнее значение и повторно выдает его для любых будущих подписчиков.

Редактировать

Я должен проверить, но я считаю, FromAsyncPattern используетAsyncSubject внутренне, поэтому фактически уже «обрезано».

Однако, если вы работали с другим горячим источником, который этого не делал, использование Prune полностью сводится к времени жизни IObservable до подписка.Если вы подписываетесь на него мгновенно, Prune не требуется.Если IObservable будет существовать некоторое время, прежде чем будет подписан, он может быть уже завершен.

Насколько я понимаю, как человек, который портировал Rx, но никогда не использовал Prune.Может быть, вам стоит задать тот же вопрос на форумах Rx ?У вас есть шанс, что кто-то из команды Rx ответит на него.

1 голос
/ 27 января 2013

Я также нашел изящное применение для этого, когда у меня есть несколько компонентов пользовательского интерфейса, которые должны прослушивать задачу (например, обратный вызов), и по умолчанию Subscribe () в холодной наблюдаемой будет запускать эту задачу несколько раз.как правило, это не то, что вам нужно, когда вы делитесь состоянием между компонентами пользовательского интерфейса.

Я знаю, что Ричард упомянул много этих моментов, но я подумал, что это идеальный кандидат для однократных задач, чтобы добавить этот пример в.

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"); });
...