Одноразовое значение, возвращаемое методами расширения Subscribe
, возвращается исключительно для того, чтобы вы могли вручную отписаться от наблюдаемой до , наблюдаемое естественным образом заканчивается.
Если наблюдаемое завершается - либоOnCompleted
или OnError
- тогда подписка уже выбрана для вас.
Попробуйте этот код:
var xs = Observable.Create<int>(o =>
{
var d = Observable.Return(1).Subscribe(o);
return Disposable.Create(() =>
{
Console.WriteLine("Disposed!");
d.Dispose();
});
});
var subscription = xs.Subscribe(x => Console.WriteLine(x));
Если вы запустите выше, вы увидите, что "Disposed!"записывается в консоль, когда наблюдаемое завершается без необходимости вызова .Dispose()
для подписки.
Одна важная вещь, на которую следует обратить внимание: сборщик мусора никогда не вызывает .Dispose()
для наблюдаемых подписок, поэтому вы должны утилизируйте ваши подписки, если они не закончились (или могут не иметь) закончились до того, как ваша подписка выйдет за рамки.
Возьмите это, например:
var wc = new WebClient();
var ds = Observable
.FromEventPattern<
DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => wc.DownloadStringCompleted += h,
h => wc.DownloadStringCompleted -= h);
var subscription =
ds.Subscribe(d =>
Console.WriteLine(d.EventArgs.Result));
The ds
observable будет подключаться к обработчику событий только тогда, когда у него есть подписка, и будет отключаться только после завершения наблюдения или удаления подписки.Поскольку это обработчик событий, наблюдаемое никогда не завершится, потому что оно ожидает большего количества событий, и, следовательно, удаление - единственный способ отсоединиться от события (для приведенного выше примера).
Когда у вас есть FromEventPattern
Заметим, что вы знаете, что когда-либо будет возвращать только одно значение, тогда разумно добавить метод расширения .Take(1)
перед подпиской, чтобы позволить обработчику событий автоматически отключаться, и тогда вам не нужно вручную удалять подписку.
Вот так:
var ds = Observable
.FromEventPattern<
DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => wc.DownloadStringCompleted += h,
h => wc.DownloadStringCompleted -= h)
.Take(1);
Надеюсь, это поможет.