10

ブログから ReactiveUi の例を見てきましたが、ReactiveUI が何らかのサブスクリプション管理機能を持っているのか、それともサブスクリプションをリークする可能性があるという事実を無視している例なのか疑問に思っています。

ReactiveUi でメソッドを呼び出して結果が になるときはいつでも、IDisposableその参照を保持して自分で追跡する必要がありますか? また、これは ViewModel を使い捨てにする必要があることを意味しますか? WPF では、接続された「ビュー」がいつ消えるか (つまり、ViewModel がデータ グリッドのアイテムを反映するか) がわからないため、これは難しいようです。処分する場所。

4

3 に答える 3

15

また、Rx および ReactiveUI によって返される IDisposables はアンマネージ メモリに関連付けられていないことも覚えておく必要があります。これはすべて単純な .NET オブジェクトであり、まだガベージ コレクターによって参照されています。

ReactiveObjects のコンストラクターで作成するサブスクリプションのほとんどは、ホスト オブジェクトの有効期間に関連付けられます。そのため、スコープ外に出て GC の対象になると、すべてのサブスクリプションも同様に、CLR が循環参照を検出し、すべてを核にするだけです。

Enigmativity が言及しているように、1 つのトリッキーなビットは、FromEventPattern を使用して Subscription (およびおそらく ViewModel) の有効期間を WPF オブジェクトの有効期間に結び付ける場合です。ただし、ReactiveUI で FromEventPattern を頻繁に使用している場合は、間違いなく Doing It Wrong™ であると私は主張します。

RxUI はすべて ViewModel に関するものであり、ViewModel はすべてコマンドプロパティに関するものです (また、プロパティが相互にどのように関連しているかを結び付けます) 。そのため、ビジュアルとは別にユーザー エクスペリエンスの動作をテストできます。

于 2012-01-26T07:32:55.953 に答える
12

オブザーバブルから早期IDisposableにサブスクライブを解除する必要がある場合にのみ、サブスクリプションによって返された参照を保持する必要があります。Observableは、またはメッセージのいずれかで終了すると、自然に呼び出します。DisposeOnCompletedOnError

ただし、監視可能なサブスクリプションが無限にある場合(つまりFromEventPattern)は参照を保持する必要がありますが、これは、フォーム/ビューを閉じる前にイベントハンドラーを削除する必要がある場合とまったく同じです。

于 2012-01-19T00:41:11.460 に答える
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 を自動的に生成された拡張メソッドでラップしているため、覚えにくい FromEventPattern の形式ではなく、無料で SizeChangedObserver() と UnloadedObserver() を取得します。

ラッピングコードはそのまま生成されます

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

上記のパターンは、おそらく IDisposable ビュー モデルのバインドを解除するためにも使用できます。

于 2013-03-26T16:43:04.310 に答える