Benjol
Benjol

Reputation: 66541

Subscribe to Observable.Retry() doesn't return until it completes?

I expect IObservable.Subscribe to be asynchronous: whatever happens inside, I would like my subscription back.

But Retry seems to have a different semantic:

var retry = Observable.Throw(new Exception(), 0).Retry();
Console.WriteLine("got here");
var subscription = retry.Subscribe();
Console.WriteLine("didn't get here, ever");

There is clearly something I don't understand here. I guess using Retry with no parameters can't be used very often, or it should be used for something that I haven't thought of.

Upvotes: 1

Views: 175

Answers (1)

James World
James World

Reputation: 29786

The problem isn't anything to do with Retry - it's Observable.Throw because it defaults to scheduling its OnError on the immediate scheduler. Change your first line to this and you are golden:

var retry = Observable.Throw<int>(new Exception(), Scheduler.Default).Retry();

In general Rx tries to use the most immediate scheduler it can. Scheduler.Default will use the current platform's preferred scheduler that introduces concurrency.

Retry will initially subscribe on the current thread (which is fine) and then subscribe for each retry on whatever thread Throw terminates on.

EDIT

Although the fix above works - it's probably not the best way. It's actually good that Throw and Retry try to use the immediate scheduler as this is the most computationally efficient way. The code above will cause every iteration of Throw to run on a different thread.

A better and more idiomatic Rx solution would be to edit the third line instead:

var subscription = retry.SubscribeOn(Scheduler.Default).Subscribe();

This causes only the initial subscription to Retry to happen asynchronously on a different Thread - and the rest of the processing will stay on that one thread.

Upvotes: 1

Related Questions