RxUI - 为每个事务或流处理对象创建一个侦听器更好吗?

时间:2017-05-04 11:51:38

标签: c# reactiveui

在过去的3-4个月里,我发现,默认情况下或者只是巧合,我的所有RxUI可观察量(.Subscribe)都是在各种对象中创建的。构造函数(代码)。但是,该应用程序还大量使用监视各种流并执行操作(更新UI,创建事务等)的后台任务,有时,这些任务需要中止某些事务。所以,我只是想知道哪里最好的地方'实例化一个听众'中止指令(旗帜)?在交易对象中创建或在“监督”范围内。监控流的对象?如果在交易中,对业绩和处置有何影响?我知道这是一个相当广泛的问题,但我希望有人可以推荐一个合适的模式。任何指针,评论赞赏。

请参阅下面的模拟代码:

using System;
using System.Threading.Tasks;
using System.Threading;

using ReactiveUI;

using UserSettingsClassLibrary;

namespace fxR.UTILITIES.MockCode
{
    public class MockRxUI_AbortTransaction : ReactiveObject { } // ignore this class

    public class ManageTransactions : ReactiveObject
    {
        // properties
        CancellationTokenSource ctTransactionPosition;

        // constructor
        public ManageTransactions()
        {
            // initialise
            ctTransactionPosition = new CancellationTokenSource();
        }

        // methods
        public async Task OpenTransaction(MyStreamProcessingObject sPO, string user, string openTransactionAction)
        {
            // ... create transaction object, db log, etc

            // open a 'listener' in case this Transaction is aborted
            if (user.Contains("/"))
            {
                sPO.WhenAnyValue(x => x.ActiveObject.AbortTrade)
                    .Log(this, "TransactionOpen -> Abort trigger ")
                    .Subscribe(abort =>
                    {
                        if (sPO.ActiveObject.TradeOpen && abort)
                        {
                            // abort
                        }
                    });
            }
        }
    }

    // the OpenTransaction method above would be called from elsewhere in the app, eg
    public class SomeOtherObject : ReactiveObject
    {
        ManageTransactions _manageTransactions;
        MyStreamProcessingObject _sPO;

        public SomeOtherObject(MyStreamProcessingObject sPO)
        {
            _sPO = sPO;
            _manageTransactions = new ManageTransactions();
        }

        public async Task DoSomethingAsync()
        {
            await _manageTransactions.OpenTransaction(_sPO, Environment.UserName + "/" + GetType().Name, "TransactionAction").ConfigureAwait(false);
        }
    }
    // ================================================================================================
    // OR, open a 'listener' on the Stream Processing Object when it is constructed (first initialised)
    // ================================================================================================

    public class MyStreamProcessingObject : ReactiveObject
    {
        // object properties
        private ActiveObject _activeObject;
        public ActiveObject ActiveObject
        {
            get { return _activeObject; }
            set { this.RaiseAndSetIfChanged(ref _activeObject, value); }
        }

        // constructor
        public MyStreamProcessingObject()
        {
            // listen for Transaction abort status
            this.WhenAnyValue(x => x.ActiveObject.AbortTrade)
                .Log(this, "Log -> ActiveObject.AbortTransaction")
                .Subscribe(async abort =>
                {
                    if (abort)
                    {
                        await Task.Run(async () => await AbortOpenAutoTransaction().ConfigureAwait(false));
                    }
                });
        }

        // methods
        private async Task AbortOpenAutoTransaction()
        {
            var ok = false;
            // await some abort code, if all ok, set ok = true;
            if (ok) ActiveObject.AbortTrade = false;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我可以在async/await之前就订阅和一次性用品给你一些建议。您可以使用以下模式。

async Task<int> Foo(IObservable<bool> observable, Task<int> task){

    var subscription = observable.Subscribe
        ( x => Console.WriteLine("WhooHoo");

    using(subscription)
    {
        var value = await task;
        return value + 10;
    }   
} 

相当于

async Task<int> Foo(IObservable<bool> observable, Task<int> task){

    var subscription = observable.Subscribe
        ( x => Console.WriteLine("WhooHoo");

    try
    {
        var value = await task;
        return value + 10;
    }finally{
        subscription.Dispose();
    } 
} 

任务完成后,将处理订阅。

但是,如果您发现在构造函数中创建订阅,那么您需要另一种模式。

public class Foo : ReactiveObject, IDisposable {
   private CompositeDisposable _Cleanup = new CompositeDisposable();

   public Foo(IObservable<int> observable){
       var subscription = observable
            .Subscribe(x=>Console.WriteLine("WhooHoo"));
       _Cleanup.Add(subscription);     

   }

   public void Dispose(){
       _Cleanup.Dispose();
   }
}

或更好地使用RXUI扩展方法DisposeWith

public class Foo : ReactiveObject, IDisposable {
   private CompositeDisposable _Cleanup = new CompositeDisposable();

   public Foo(IObservable<int> observable){
       observable
            .Subscribe(x=>Console.WriteLine("WhooHoo"))
            .DisposeWith(_Cleanup);
   }

   public void Dispose(){
       _Cleanup.Dispose();
   }
}

通常我会创建一个基类

public class DisposableReactiveObject : ReactiveObject, IDisposable {
   protected CompositeDisposable Cleanup { get; } = new CompositeDisposable;
   public void Dispose(){
       _Cleanup.Dispose();
   }
}

然后可以将其用作

public class Foo : DisposableReactiveObject {
   public Foo(IObservable<int> observable){

       observable
            .Subscribe(x=>Console.WriteLine("WhooHoo"))
            .DisposeWith(Cleanup);

   }
}
相关问题