反应:试图了解受试对象; T>工作 [英] Reactive: Trying to understand how Subject<T> work
问题描述
试图了解如何使用受试对象; T>
, ReplaySubject< T>
等工作。下面是例子:
(主题是可观的和观察者)
公开的IObservable< INT> CreateObservable()
{
受试对象; INT> SUBJ =新的受试对象;诠释>(); //情况1
ReplaySubject< INT> SUBJ =新ReplaySubject<&诠释GT;(); //情况下2
随机RND =新的随机();
INT maxValue分别= rnd.Next(20);
Trace.TraceInformation(最大的价值是:+ maxValue.ToString());
subj.OnNext(-1); //特定值
为(INT iCounter = 0; iCounter<包括maxValue; iCounter ++)
{
Trace.TraceInformation(值:+ iCounter.ToString()+ 即将发布);
subj.OnNext(iCounter);
}
Trace.TraceInformation(发布完成);
subj.OnComplete();
返回SUBJ;
}
公共无效的主要()
{
//
//第一个收费
CreateObservable()
.Subscribe (
onNext:(X)= GT; {
Trace.TraceInformation(X为:+ x.ToString());
});
//
//第二认购
CreateObservable()
.Subscribe(
onNext:(×2)=> {
跟踪.TraceInformation(X 2是:+ x.ToString());
});
案例1:奇怪的情况是 - 当我使用受试对象; T>
没有订阅时(???) - 我从来没有看到的X是:文字 - 我只看到了值是:和最大值是......为什么受试对象; T>
不压值订阅
案例2:如果我使用 ReplaySubject< ; T>
- 我确实看到订阅的值,但我不能适用推迟
选项任何东西。不要主题
,而不是观测....所以每认购将获得不同的值,因为 CreateObservable
函数的冷的观测。哪里是推迟
?
您需要铭记,当代码被执行
在案例1,当您使用受试对象; T>
,你会发现该所有呼叫到 OnNext
&安培;前观察到的 OnCompleted
完成由 CreateObservable
方法返回。由于您使用的是受试对象; T>
这意味着任何后续订阅将错过所有的值,所以你应该希望得到你得到了什么 - 没有什么。
您不得不推迟关于这个问题的操作,直到你有订阅的观察者。要做到这一点使用创建
方法。具体方法如下:
公开的IObservable< INT> CreateObservable()
{
返回Observable.Create< INT>(O =>
{
变种SUBJ =新的受试对象; INT>();
无功弃= subj.Subscribe(O);
变种RND =新的随机();
变种包括maxValue = rnd.Next(20);
subj.OnNext(-1);
为(INT iCounter = 0; iCounter<包括maxValue; iCounter ++)
{
subj.OnNext(iCounter);
}
subj.OnCompleted();
返回支配;
});
}
我已经删除了所有的跟踪代码简洁。
所以,现在,对于每一个用户,你进去代码的一个新的执行创建
方法和你现在会从获取值内部受试对象; T>
使用的创建$ C 。$ C>方法通常是创建从方法返回观测的正确方法
另外,您可以使用 ReplaySubject< T>
并避免使用创建
的方法。然而,这是不具吸引力的多种原因。它迫使整个序列的创建时间计算。这给你一个寒冷的观察到的,你本来可以更有效地生产,而无需使用重播主题。
现在,顺便说一句,你应该尽量避免使用对象的。一般的规则是,如果你使用一个主题,那么你正在做的事情是错误的。在 CreateObservable
方法将被更好地写成这样:
公开的IObservable< INT> CreateObservable()
{
返回Observable.Create< INT>(O =>
{
变种RND =新的随机();
变种包括maxValue = RND。下一页(20);
返回Observable.Range(-1,包括maxValue + 1).Subscribe(O);
});
}
没有必要的对象都没有。
让我知道,如果这有助于。
Trying to understand how the Subject<T>
, ReplaySubject<T>
and other work. Here is example:
(Subject is Observable and observer)
public IObservable<int> CreateObservable()
{
Subject<int> subj = new Subject<int>(); // case 1
ReplaySubject<int> subj = new ReplaySubject<int>(); // case 2
Random rnd = new Random();
int maxValue = rnd.Next(20);
Trace.TraceInformation("Max value is: " + maxValue.ToString());
subj.OnNext(-1); // specific value
for(int iCounter = 0; iCounter < maxValue; iCounter++)
{
Trace.TraceInformation("Value: " + iCounter.ToString() + " is about to publish");
subj.OnNext(iCounter);
}
Trace.TraceInformation("Publish complete");
subj.OnComplete();
return subj;
}
public void Main()
{
//
// First subscription
CreateObservable()
.Subscribe(
onNext: (x)=>{
Trace.TraceInformation("X is: " + x.ToString());
});
//
// Second subscribe
CreateObservable()
.Subscribe(
onNext: (x2)=>{
Trace.TraceInformation("X2 is: " + x.ToString());
});
Case 1: The strange situation is - when I use Subject<T>
no subscription is made (???) - I never see the "X is: " text - I only see the "Value is: " and "Max value is"... Why does Subject<T>
does not push values to subscription ?
Case 2: If I use ReplaySubject<T>
- I do see the values in Subscription but I could not apply Defer
option to anything. Not to Subject
and not to Observable.... So every subscription will receive different values because CreateObservable
function is cold observable. Where is Defer
?
You need to be mindful of when code is executed.
In "Case 1", when you use a Subject<T>
, you'll notice that the all of the calls to OnNext
& OnCompleted
finish before the observable is returned by the CreateObservable
method. Since you are using a Subject<T>
this means that any subsequent subscription will have missed all of the values so you should expect to get what you got - nothing.
You have to delay the operations on the subject until you have the observer subscribed. To do that using the Create
method. Here's how:
public IObservable<int> CreateObservable()
{
return Observable.Create<int>(o =>
{
var subj = new Subject<int>();
var disposable = subj.Subscribe(o);
var rnd = new Random();
var maxValue = rnd.Next(20);
subj.OnNext(-1);
for(int iCounter = 0; iCounter < maxValue; iCounter++)
{
subj.OnNext(iCounter);
}
subj.OnCompleted();
return disposable;
});
}
I've removed all the trace code for succinctness.
So now, for every subscriber, you get a new execution of the code inside the Create
method and you would now get the values from the internal Subject<T>
.
The use of the Create
method is generally the correct way to create observables that you return from methods.
Alternatively you could use a ReplaySubject<T>
and avoid the use of the Create
method. However this is unattractive for a number of reasons. It forces the computation of the entire sequence at creation time. This give you a cold observable that you could have produced more efficiently without using a replay subject.
Now, as an aside, you should try to avoid using subjects at all. The general rule is that if you're using a subject then you're doing something wrong. The CreateObservable
method would be better written as this:
public IObservable<int> CreateObservable()
{
return Observable.Create<int>(o =>
{
var rnd = new Random();
var maxValue = rnd.Next(20);
return Observable.Range(-1, maxValue + 1).Subscribe(o);
});
}
No need for a subject at all.
Let me know if this helps.
这篇关于反应:试图了解受试对象; T>工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!