Edit:
Examining your code more closely, I'd recommend using Observable.Create
. Even though it only returns a cold observable, you can apply the Publish
operator to the generated observable to make it hot.
And if by task
you're actually referring to Task<T>
, then you can use an overload of Observable.Create
that allows you to define an async iterator. For example:
IObservable<string> statuses = Observable.Create<string>(
(observer, cancel) =>
{
foreach (var task in todo)
{
cancel.ThrowIfCancellationRequested();
await task;
observer.OnNext("Status");
}
});
Previous Answer:
You could use one of the following types, but I suggest reading To Use Subject or Not To Use Subject first before making your decision.
Subject<T>
: General purpose, "event"-like, hot observable. Calling OnNext
is like raising a classic .NET event.
BehaviorSubject<T>
: Generally used as the backing field for a property, it represents an observable sequence of change "events". Whenever an observer subscribes, it receives the current value immediately, followed by all changes to the property. You can extract the current value at any time from the Value
property; e.g., within your property's getter. Call OnNext
within your property's setter and you don't have to keep a duplicate backing field. It's also Rx's version of a continuous function and it's the only FRP-like thing you'll find in Rx, if my understanding of FRP is correct.
ReplaySubject<T>
: Generally used as an historical buffer of "events", it represents an observable sequence of values beginning with the values that have been missed by an observer, whenever an observer subscribes. You can control how far back values are buffered; it's like a sliding window over the history of values. You rarely have to use this type. In most cases, the Observable.Replay
operator will do.
AsyncSubject<T>
: Generally used to capture the results of hot, asynchronous functions like Task<T>
. You rarely have to use this type. In most cases, Observable.FromAsyncPattern
or Task
-conversion operators will do.