subject.Dispose() 对比 subject.OnCompleted()
subject.Dispose() vs subject.OnCompleted()
在 Subject
上调用 .Dispose()
和 .OnCompleted()
有什么区别?
通常我会安排订阅以停止监听可观察对象并在代码中的任何地方不再有用时完成一个主题,
Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer usefull[sic] anywhere on the code
我认为你把那些倒退了。我不熟悉 rx.net,但我知道 IDisposable 和 Observable 模式。 IDisposable 用于在您完全使用完某个对象并且不再有用时从该对象释放资源。 OnCompleted 用于当您完成观察(提供者已完成发送通知)时,即使该对象可能仍有其他用途。
根据Subject<T>.Dispose
方法的documentation:
Releases all resources used by the current instance of the Subject<T>
class and unsubscribe all observers.
似乎在处理 Subject
之后尝试对它做任何事情都会导致 ObjectDisposedException
。例如,您不能 Subscribe
到已处置的 Subject
。在处理 Subject
时处于活动状态的任何订阅也将被处理,并且未订阅的观察者将 不会 收到 OnCompleted
通知。
相反,通过调用其 OnCompleted
方法完成的主题仍然可以随时订阅,在这种情况下订阅的观察者将立即收到 OnCompleted
通知。当然,如果完成的主题是像ReplaySubject
这样的缓冲类型之一,那么观察者将在最终OnCompleted
.
之前收到许多OnNext
通知。
我个人会考虑调用Dispose
到一个即将被丢弃的ReplaySubject
,以加速其内部缓冲区使用的RAM的回收。我不确定这是否会有所不同,因为 Dispose
通常应该释放非托管资源,并且缓冲区使用的内存很可能是托管的。
在主题上调用 .Dispose()
和 .OnCompleted()
之间存在非常重要的语义差异。
考虑这段代码:
Subject<int> subject = new Subject<int>();
IObservable<int[]> query = subject.ToArray();
IDisposable subscription =
query
.Subscribe(xs => Console.WriteLine(String.Concat(xs)));
subject.OnNext(1);
subject.OnNext(2);
如果我随后调用 subject.OnCompleted()
,我会将 12
写入控制台。但是,如果我调用 subject.Dispose()
,则不会打印任何内容。
一些运算符,例如我的示例代码中的 .ToArray()
,期望 .OnCompleted()
调用产生任何值。
了解您在 subject
上执行的查询以了解如何正确结束它很重要 - 在某些情况下两种方式都有效。
不过,我觉得您处理订阅和完成科目的做法是正确的。
在 Subject
上调用 .Dispose()
和 .OnCompleted()
有什么区别?
通常我会安排订阅以停止监听可观察对象并在代码中的任何地方不再有用时完成一个主题,
Usually i dispose subscription to stop listening an observable and complete a subject when it's no longer usefull[sic] anywhere on the code
我认为你把那些倒退了。我不熟悉 rx.net,但我知道 IDisposable 和 Observable 模式。 IDisposable 用于在您完全使用完某个对象并且不再有用时从该对象释放资源。 OnCompleted 用于当您完成观察(提供者已完成发送通知)时,即使该对象可能仍有其他用途。
根据Subject<T>.Dispose
方法的documentation:
Releases all resources used by the current instance of the
Subject<T>
class and unsubscribe all observers.
似乎在处理 Subject
之后尝试对它做任何事情都会导致 ObjectDisposedException
。例如,您不能 Subscribe
到已处置的 Subject
。在处理 Subject
时处于活动状态的任何订阅也将被处理,并且未订阅的观察者将 不会 收到 OnCompleted
通知。
相反,通过调用其 OnCompleted
方法完成的主题仍然可以随时订阅,在这种情况下订阅的观察者将立即收到 OnCompleted
通知。当然,如果完成的主题是像ReplaySubject
这样的缓冲类型之一,那么观察者将在最终OnCompleted
.
OnNext
通知。
我个人会考虑调用Dispose
到一个即将被丢弃的ReplaySubject
,以加速其内部缓冲区使用的RAM的回收。我不确定这是否会有所不同,因为 Dispose
通常应该释放非托管资源,并且缓冲区使用的内存很可能是托管的。
在主题上调用 .Dispose()
和 .OnCompleted()
之间存在非常重要的语义差异。
考虑这段代码:
Subject<int> subject = new Subject<int>();
IObservable<int[]> query = subject.ToArray();
IDisposable subscription =
query
.Subscribe(xs => Console.WriteLine(String.Concat(xs)));
subject.OnNext(1);
subject.OnNext(2);
如果我随后调用 subject.OnCompleted()
,我会将 12
写入控制台。但是,如果我调用 subject.Dispose()
,则不会打印任何内容。
一些运算符,例如我的示例代码中的 .ToArray()
,期望 .OnCompleted()
调用产生任何值。
了解您在 subject
上执行的查询以了解如何正确结束它很重要 - 在某些情况下两种方式都有效。
不过,我觉得您处理订阅和完成科目的做法是正确的。