Dot-Net

使用 .NET 的響應式擴展時保持對“IDisposable”的引用:總是、從不還是有時?

  • May 29, 2013

到目前為止,我一直在熱心地保留對IDisposable從任何 , 等方法返回的.Subscribe(...)每個.Connect(...)引用在 Rx 中。我這樣做是因為我擔心如果我不保留引用,垃圾收集器會丟棄一次性物品。

但是,我在 LINQPad 中做了一個測試,我在沒有保留參考GC.Collect()的地方做了一些呼叫,你猜怎麼著?.Subscribe(...)世界並沒有結束,訂閱已經完成。

在進一步的測試中,我發現我的訂閱在.OnComplete()沒有我干預的情況下立即被處理掉了。

這讓我明白,至少對於.Subscribe(...),保留對訂閱的引用的唯一原因是強制訂閱在其正常完成之前結束。它更像是一個取消令牌。

那麼所有 Rx 一次性用品都用於取消而不是保持活力嗎?

那麼,什麼是堅持的規則IDisposable

僅當您想取消計劃的操作(即它發生之前)時,IDisposable返回的 by才有用IScheduler.Schedule()

和的IDisposable返回值是等價的,因為處理任何一個都將終止對源 observable 的訂閱。IObservable.Subscribe``IConnectableObservable.Connect

至於垃圾收集,雖然 Rx 使其更難以衡量,但它仍然受 GC 規則的約束。如果你的 observable 的源是 root 的(比如 UI 控制項的事件),那麼你不需要擔心它會被 GC 處理。

如果你的源是 aObservable.Interval或其他東西基本上是一個遞歸IScheduler呼叫,那麼調度程序應該讓它保持活動狀態(即執行緒池、任務池或調度程序),因為 observable 植根於調度程序(通過IScheduler.Schedule)。

除非您想在將來取消訂閱可觀察的源,否則無需保留 IDisposable 對象。與 IScheduler 上的 Schedule 方法類似,其返回的 IDisposable 對象可用於取消計劃的操作。

垃圾收集器不直接關心 IDisposable 對象,我們也不在我們的任何對像上實現終結器,所以基本上訂閱等的生命週期管理在 Rx 的世界中完全取決於你。如果您願意,可以將其與 Win32 句柄進行比較,Dispose 在道德上等同於 CloseHandle。

瑣事:在設計 Rx 期間的某個時刻,可取消操作返回了一個 Action,其呼叫將導致取消。在自然界中頗受功能啟發,但對某些人來說不太明顯。因此,我們決定使用已經代表資源管理概念的介面,而 IDisposable 是顯而易見的選擇。這就是說,它與 .NET Framework 中其他地方的介面的典型用法有所不同:

  • 您通常會將 IDisposable 對象放在地板上,特別是對於您從未取消訂閱的無限序列。
  • 在大多數情況下,由於框架固有的非同步特性,您不會對 Rx IDisposable 對象使用 using 語句。

希望這可以幫助,

-巴特(Rx 團隊)

引用自:https://stackoverflow.com/questions/5227823