Что делают различные реализации ISubject и когда они будут использоваться? - PullRequest
26 голосов
/ 25 января 2011

У меня довольно хорошее представление о том, что делает класс Subject и когда его использовать, но я только что просмотрел справочник по языку в msdn и вижу, что существуют различные другие реализации ISubject, такие как:

  • AsyncSubject
  • BehaviorSubject
  • ReplaySubject

Поскольку документация довольно тонкая на местах, какой смысл каждого из этих типов и в каких ситуацияхВы бы их использовали?

Ответы [ 4 ]

23 голосов
/ 25 января 2011

Все эти субъекты имеют общее свойство - они берут часть (или все) того, что им сообщают через OnNext, записывают и воспроизводят это вам - то есть они берут горячую наблюдаемость и делают ее холодной. Это означает, что если вы подписываетесь на какой-либо из них более одного раза (т. Е. Подписаться => Отменить подписку => Подписаться снова), вы увидите по крайней мере один того же значения снова.

ReplaySubject : Каждый раз, когда вы подписываетесь на тему, вы получаете всю историю того, что было опубликовано, воспроизводится вам как можно быстрее (или подмножество, как в последнем n). предметов)

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

BehaviorSubject : Вроде как ReplaySubject, но с одним буфером, так что вы всегда получаете последнее, что было опубликовано. Вы также можете предоставить начальное значение. Всегда предоставляет один элемент при подписке.

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

В свете последней версии ( v1.0.2856.0 ) и для поддержания актуальности этого вопроса появился новый набор предметных классов:

FastSubjectFastBehaviorSubject, FastAsyncSubject и FastReplaySubject

Согласно примечаниям к выпуску они

намного быстрее, чем обычные предметы, но:

  • не разъединяет производителя и потребителя с помощью IScheduler (фактически ограничивая их ImmediateScheduler);
  • не защищает от переполнения стека;
  • не синхронизирует входные сообщения.

Быстрые объекты используются операторами Publish и Prune, если не указан планировщик.

5 голосов
/ 15 февраля 2011

В отношении AsyncSubject

Этот код:

        var s = new AsyncSubject<int>();
        s.OnNext(1);
        s.Subscribe(Console.WriteLine);
        s.OnNext(2);
        s.OnNext(3);
        s.OnCompleted();

печатает одно значение 3. И оно печатает то же самое, если подписка перемещается на после завершения.Таким образом, он воспроизводит не первый, а последний элемент, воспроизводит его после завершения (до завершения он не выдает значения) и не работает как Subject до завершения.См. это обсуждение Prune для получения дополнительной информации (AsyncSubject в основном совпадает с Prune)

4 голосов
/ 25 января 2011

Ответ Пола в значительной степени прибивает его.Однако стоит добавить несколько вещей:

AsyncSubject работает, как говорит Пол, но только после завершения source .До этого он работал как Subject (где подписчики получают «живые» значения)

AsyncSubject изменился с тех пор, как я в последний раз выполнял тесты для него.Он больше не действует как живой объект до завершения, но ожидает завершения, прежде чем он выдаст значение.И, как упоминает Сергей, он возвращает последнее значение, а не первое (хотя я должен был это понять, как это всегда было)

AsyncSubject используется Prune, FromAsyncPattern, ToAsync и, возможно, несколько других

BehaviorSubject используется перегрузками Publish, которые принимают начальное значение

ReplaySubject используется Replay

ПРИМЕЧАНИЕ. Все ссылки на операторы, приведенные выше, относятся к набору операторов публикации, каким они были до замены на обобщенные операторы публикации в Rev 2838 (Christmas '10), посколькубыло упомянуто, что оригинальные операторы будут повторно добавлены

...