2

I'm trying to figure out how to "restart" an IConnectableObservable after it has completed or errored.

The code below shows two subscribers (A, B) to a connnectable observable. Once their subscription is disposed, a new subscriber (C) connects. I'd like it to appear to C that it is an entirely new observable, but I am only getting the exception raised in the first subscription.

static void Main(string[] args)
{
    var o = Observable.Create<string>(observer =>
        {
            observer.OnNext("msg");
            observer.OnError(new Exception("boom"));
            return Disposable.Create(() => {
                Console.WriteLine("Observer has unsubscribed");
            });
        }
    )
    .Publish();

    o.Subscribe(
        x => Console.WriteLine("A: " + x),
        ex => Console.WriteLine("A: " + ex),
        () => Console.WriteLine("A: done"));

    o.Subscribe(
        x => Console.WriteLine("B: " + x),
        ex => Console.WriteLine("B: " + ex),
        () => Console.WriteLine("B: done"));            

    var subscription = o.Connect();

    subscription.Dispose();

    o.Subscribe(
        x => Console.WriteLine("C: " + x),
        ex => Console.WriteLine("C: " + ex),
        () => Console.WriteLine("C: done"));        

    subscription = o.Connect();

}

gives the following result:

A: msg
B: msg
A: System.Exception: boom
B: System.Exception: boom
Observer has unsubscribed
C: System.Exception: boom
Observer has unsubscribed

whereas I would like:

A: msg
B: msg
A: System.Exception: boom
B: System.Exception: boom
Observer has unsubscribed
C: msg
C: System.Exception: boom
Observer has unsubscribed

Any ideas? Thanks!

MarkNS
  • 3,811
  • 2
  • 43
  • 60
  • If you've published the observable and it's run to completion then it can't produce more values. You need to start with a `Func>` to get the behaviour that you want. Is there a real-world problem you're trying to solve? – Enigmativity Dec 10 '17 at 21:58
  • Hey @Enigmativity, I'm actually revisiting a question that you helped me with a few weeks back (https://stackoverflow.com/questions/46911672/reactivecommand-and-connectableobservable) - turns out that I would prefer the observable to complete or error, to provide proper lifetime management. Obviously, in the case of the shared observable this means that the stream cannot be restarted once it has completed - as indeed you warned me about! https://stackoverflow.com/questions/46911672/reactivecommand-and-connectableobservable#comment80793509_46911974. – MarkNS Dec 11 '17 at 05:55
  • I've decided to refactor my application slightly to remove the need for the shared observable entirely - it was creating more trouble that it was worth. If you want to provide an answer stating that it's not possible to restart an `IConnectableObservable` together with an example of the `Func>` work around then I'll be happy to accept though. Cheers. – MarkNS Dec 11 '17 at 05:59

1 Answers1

0

While it doesn't "restart" the observable, replacing Publish with Replay provides the output you are expecting. However, keep in mind this will buffer all of the values from the source observable. It's best to put a limit on the number of replayed values.

Taylor Buchanan
  • 4,155
  • 1
  • 28
  • 40