Реактивные расширения, которые использует субъект

Я нахожусь на ранних этапах изучения Rx и наткнулся на класс Subject. Я не совсем понимаю, почему этот класс существует. Я понимаю, что он реализует как IObservable, так и IObserver, но для чего используются субъекты?

Насколько я могу судить, они могут действовать как прокси между источником и группой подписчиков, но не могут ли подписчики просто подписаться непосредственно на источник? Когда я вижу экземпляры Subject, используемые в качестве наблюдаемого и наблюдателя, я путаюсь.

Я уверен, что просто не улавливаю некоторые основные факты, но я не знаю, что Субъект привносит в игру. Думаю, я ищу какой-то базовый (но, надеюсь, реальный) пример того, когда субъекты полезны, а когда нет (поскольку я также читал, что субъекты обычно не используются, заменены на Observable.Create).


person Flack    schedule 31.01.2013    source источник
comment
Вы не должны использовать Subjects в большинстве случаев. См. этот вопрос: stackoverflow.com/questions/14396449/   -  person Aleš Roubíček    schedule 04.02.2013


Ответы (2)


Во-первых, многие люди скажут вам, что Subject<T> не подходит, так как это противоречит некоторым другим принципам/шаблонам в структуре Rx.

Тем не менее, они действуют либо как IObservable, либо как IObserver, поэтому вы получаете от них некоторую полезную функциональность — я обычно использую их на начальных этапах разработки для:

  • Своего рода «точка отладки», где я могу подписаться на цепочку IObservable, встроенную в Subject<T>, и проверять содержимое с помощью отладчика.

  • «Наблюдаемый по запросу», где я могу вручную вызвать OnNext и передать данные, которые я хочу ввести в поток

  • Раньше использовал их, чтобы воспроизвести то, что сейчас делает ConnectableObserable — механизм «трансляции» для нескольких подписчиков на один Observable, но теперь это можно сделать с Publish.

  • Промежуточный слой между разрозненными системами; опять же, теперь это в значительной степени не нужно с различными расширениями FromAsync, FromEvent, но их все еще можно использовать как таковые (в основном, «старая» система вводит события в Subject<T> через OnNext, а затем в обычный поток Rx.

person JerKimball    schedule 31.01.2013

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

Существенным преимуществом метода Create по сравнению с субъектами является то, что последовательность будет оцениваться лениво.

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

Пример ниже будет заблокирован как минимум на 1 секунду, прежде чем они даже получат IObservable, независимо от того, действительно ли они подписаны на него или нет.

private IObservable<string> BlockingMethod()
{
var subject = new ReplaySubject<string>();
subject.OnNext("a");
subject.OnNext("b");
subject.OnCompleted();
Thread.Sleep(1000);
return subject;
}

Где, как в примере bleow, потребитель немедленно получает IObservable и будет нести затраты на спящий режим только в том случае, если они подпишутся.

private IObservable<string> NonBlocking()
{

return Observable.Create<string>(

(IObserver<string> observer) =>
{

observer.OnNext("a");
observer.OnNext("b");
observer.OnCompleted();
Thread.Sleep(1000);
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
//or can return an Action like 
//return () => Console.WriteLine("Observer has unsubscribed"); 
});
}
person Rajnikant    schedule 28.06.2015