簡體   English   中英

反應性可觀察認購出售事項

[英]Reactive Observable Subscription Disposal

如果我可以訪問我知道只會返回一個項目的IObservable,這是否有效並且它是最好的使用模式?

IDisposable disposable = null;
disposable = myObservable.Subscribe(x =>
  {
     DoThingWithItem(x);
     if (disposable != null)
     {
       disposable.Dispose();
     }
  });

Subscribe擴展方法返回的一次性返回僅允許您在觀察結果自然結束之前手動取消訂閱可觀察對象。

如果observable完成 - 使用OnCompletedOnError - 那么訂閱已經為您處理。

試試這段代碼:

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!” 當observable完成而不需要調用.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));

ds observable僅在具有訂閱時附加到事件處理程序,並且僅在observable完成或處理訂閱時才分離。 因為它是一個事件處理程序,所以observable永遠不會完成,因為它正在等待更多事件,因此處理是從事件中分離的唯一方法(對於上面的例子)。

如果你有一個FromEventPattern observable,你知道它只返回一個值,那么在訂閱允許事件處理程序自動分離之前添加.Take(1)擴展方法是明智的,然后你不需要手動處理訂閱。

像這樣:

var ds = Observable
    .FromEventPattern<
        DownloadStringCompletedEventHandler,
        DownloadStringCompletedEventArgs>(
            h => wc.DownloadStringCompleted += h,
            h => wc.DownloadStringCompleted -= h)
    .Take(1);

我希望這有幫助。

免責聲明:我還在學習Rx。 所以我不是真正的專家,但我相信Subscribe返回的一次性只會取消訂閱訂閱。 此外,如果源完成,就像您的情況一樣,取消訂閱會自動完成。 所以我認為Dispose存在冗余,可以安全地刪除。

有關詳細信息,請參閱此問題的答案。

Take功能將完全符合您的要求。 在這種情況下, Take(1)

與一些評論相反,從OnNext內部處理訂閱並不罕見。

雖然OnCompletedOnError處理是通過Subscribe擴展方法創建的包裝訂閱為您完成的,但您可能希望根據您正在觀察的值取消訂閱(例如在您的情況下:第一個)。 您並不總是有一個已知只生成一個值的observable。

問題是您只有在訂閱后才能獲得IDisposable 即使在它返回IDisposable取消訂閱之前,一個observable也可能會回撥OnNext (取決於它使用的IScheduler之類的東西)。

在這種情況下, System.Reactive.Disposables.SingleAssignmentDisposable派上用場。 它包裝了一個你可以分配較晚的IDisposable ,如果SingleAssignmentDisposable已經處理了SingleAssignmentDisposable ,它將立即處理它。 它還帶有一個屬性IsDisposed ,它最初為false並在調用Dispose()時設置為true

所以:

IObservable<string> source = ...;

var subscription = new SingleAssignmentDisposable();
subscription.Disposable = source.Subscribe(x =>
{
    if (subscription.IsDisposed) // getting notified though I've told it to stop
        return;
    DoThingsWithItem(x);
    if (x == "the last item I'm interested in")
        subscription.Dispose();
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM