I’m playing around with the RX libraries for .NET in C#. Can anyone explain to me why the ‘observer.OnCompleted()’ method does nothing in the following code:
var observableStream = Observable.Create<CustomMessage>(
(observer) =>
{
CustomMessage cm = new CustomMessage();
CustomMessage.Subscribe(observer.OnNext);
return Disposable.Create(
() =>
{
Console.WriteLine("Disposing...");
CustomMessage.Unsubscribe(observer.OnNext);
observer.OnCompleted(); //***Nothing happens here***
}
);
});
//IObserver.OnException()
public override void OnException(Exception e)
{
Console.WriteLine("Exception occurred - " + e.Message);
}
//IObserver.OnComplete()
public override void OnUnsubscribe()
{
Console.WriteLine("Unsubscribed...");
}
//IObserver.OnNext()
public override void HandleNextMsg(IRVMessage msg)
{
Console.WriteLine("Instance received a message");
}
IDisposable myDisposable = observableStream.Subscribe(HandleNextMsg, OnException, OnUnsubscribe);
//At some later point....
myDisposable.Dispose();
The code is intended to make a subscription to a stream of CustomMessages. It registers the observer.OnNext() method with my CustomMessage type when setting up a subscription. It then de-registers the observer.OnNext() when disposing of the subscription. All of this works correctly. My ‘HandleNextMsg()’ method is called whenever a CustomMessage is received.
At some later point when I wish to terminate my subscription I call ‘Dispose()’ and the following two lines are successfully executed:
Console.WriteLine("Disposing...");
CustomMessage.Unsubscribe(observer.OnNext);
I then receive no more CustomMessages. However the following line, although executed, does nothing:
observer.OnCompleted();
I expected it to call the line:
Console.WriteLine("Unsubscribed...");
At some point the connection between the observer and the ‘OnUnsubscribe’ method is lost and I’d like to understand exactly what’s going on. How is it that the ‘observer.OnNext()’ can be successfully de-registered, but ‘observer.OnCompleted()’ does nothing?
It’s been pointed out to me that just because I’m disposing the stream doesn’t mean I should be calling ‘OnCompleted()’ but I’d still like to understand why it doesn’t work.
The issue you are seeing is caused by the way
Observable.Createwraps the function you passed and any observers you subscribe to the resultingIObservable. Basically, the flow is:This answer is based on v1.x of RX, but I expect this did not change in v2.0.
If you have some code that needs to run no matter how the subscription ends (OnError, OnCompleted, or Dispose), I would suggest Observable.Finally.