2012-01-18 143 views
6

我已經看過ReactiveUi從博客的例子,我想知道ReactiveUI是否有某種訂閱管理工具,或者是否忽視了它們可能會泄漏訂閱的例子?ReactiveUI是否泄漏訂閱?

任何時候我在ReactiveUi中調用一個導致IDisposable的方法,是否需要保持該引用並自行跟蹤它?這也意味着我的ViewModel需要是一次性的,這似乎很難,因爲我們並不真正知道WPF中連接的「視圖」何時消失(即,如果我的ViewModel反映了數據網格中的項目),所以似乎沒有適當的放置處理。

回答

10

如果您需要取消訂閱早期,您只需要保留對訂閱返回的IDisposable的引用。當消息由OnCompletedOnError消息終止時,自然會調用Dispose

但是,當您擁有無限可觀察訂閱(即FromEventPattern)時,您需要保持引用,但這與在關閉表單/視圖之前需要刪除事件處理程序完全相同。

+0

通常情況下,如果發佈者的生命週期與用戶的生命週期相同或更短,您不必在表單關閉時刪除事件處理程序。例如,同樣的原則是否適用於ReactiveCommand? – KolA 2017-06-22 04:47:59

+1

@KolA - 我建議你明確處理所有的Rx訂閱,如果你知道有些可能仍然運行只是爲了安全。很容易擁有一個表單級別的CompositeDisposable,可以跟蹤所有的訂閱。它意味着當你退出時只有一個'.Dispose()'。像常規活動一樣,您可能會在沒有這樣做的情況下離開,但情況並非總是如此。 – Enigmativity 2017-06-22 06:02:38

13

您還必須記住,Rx和ReactiveUI返回的IDisposables不與非託管內存相關聯 - 它們都只是簡單的.NET對象,仍由垃圾回收器重新指定。

您在ReactiveObjects的構造函數中製作的大部分訂閱將與主機對象的生命週期綁定 - 因此,當它超出範圍並受GC影響時,CLR將檢測到所有訂閱循環參考,只是核武的一切。

由於Enigmativity提到,最棘手的一點是,當您使用FromEventPattern將Subscription的生命週期(也許是ViewModel)與WPF對象的生命週期相關聯時。但是,我認爲如果您經常在ReactiveUI中使用FromEventPattern,那麼您肯定會做到錯誤™。

RxUI是所有的ViewModels和的ViewModels都是關於命令性質(和接線,屬性是如何相互關聯的),所以你可以從它的視覺效果,分別測試的用戶體驗行爲

+0

但是不是使用PropertyChanged和PropertyChanging事件中的EventPattern使用的ObservedChanged「events」嗎?而不是使用掛鉤到Executed事件的命令?我想這是令我擔心的。 – Damian 2012-01-26 13:37:01

+0

不,內部ReactiveObject使用Subject,當您使用ObservableForProperty或WhenAny時,您沒有使用FromEventPattern – 2012-01-26 18:47:24

+0

好吧。感謝您的澄清。我將Enigmativity的答案標記爲答案,因爲他是第一個答案,但您的澄清對我的轉換級別至關重要。 – Damian 2012-01-26 20:26:28

2

爲了安全起見,我將從現在開始使用這種模式。我可能會修改 通過擴展方法工作,但原則是健全的。爲了確保您 不漏要刪除他們

class Mesh2D{ 

    public Mesh2D() 
    { 
     DisposeOnUnload(CreateBindings()); 
    } 

    // Register all disposables for disposal on 
    // UIElement.Unload event. This should be 
    // moved to an extension method. 
    void DisposeOnUnload(IEnumerable<IDisposable> disposables) 
    { 
     var d = new CompositeDisposable(disposables); 
     var d2 = this.UnloadedObserver() 
      .Subscribe(e => d.Dispose()); 
     var d3 = this.Dispatcher.ShutdownStartedObserver() 
      .Subscribe(e => d.Dispose()); 
     d.Add(d2); 
     d.Add(d3); 
    } 

    // Where your bindings are simply yielded and 
    // they are removed on Unload magically 
    IEnumerable<IDisposable> CreateBindings() 
    { 
     // When the size changes we need to update all the transforms on 
     // the markers to reposition them. 
     yield return this.SizeChangedObserver() 
      .Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler) 
      .Subscribe(eventArgs => this.ResetImageSource()); 

     // If the points change or the viewport changes 
     yield return this.WhenAny(t => t.Mesh, t => t.Viewport, (x, t) => x.Value) 
      .Throttle(TimeSpan.FromMilliseconds(20), RxApp.DeferredScheduler) 
      .Subscribe(t => this.UpdateMeshChanged()); 
    } 
} 

注意我包裹RX FromEventPattern自動生成 擴展方法訂閱,所以我得到SizeChangedObserver()和UnloadedObserver() 免費,而不是難以記憶的FromEventPattern格式。

包裹代碼作爲這樣

public static IObservable<EventPattern<RoutedEventArgs>> UnloadedObserver(this FrameworkElement This){ 
    return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(h => This.Unloaded += h, h => This.Unloaded -= h); 
} 

上述圖案生成很可能被用於解除綁定的IDisposable 視圖模型爲好。