Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: FlackОтветов: 2

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

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

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

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

Ответы

Ответ 1 · рейтинг 1 · JerKimball

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

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

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

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

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

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

Ответ 2 · Rajnikant

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

Существенным преимуществом метода 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");
});
}

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы