2

ブール値が true に設定された直後に更新を照会し、5 分ごとに再チェックしたい Web サービスがあります。

ここに私の現在の観察可能性があります:

        _queryDisposable = Observable
            .Interval(TimeSpan.FromMinutes(5))
            .ObserveOn(Scheduler.ThreadPool)
            .Where(i => IsProcessing)     // IsProcessing is the bool value
            .Subscribe(GetFeeds, OnError, OnComplete);

このオブザーバブルは、IsProcessingbool が true か false かを 5 分ごとにチェックし、true のGetFeeds場合は呼び出します。

目的の効果を得るために私が考えることができる唯一の方法はIsProcessing、次のような 2 つのオブザーバブルを使用して、プロパティに基づくフィールドとプロセスを作成することです。

    private bool _isProcessing;

    public bool IsProcessing
    {
        get { return _isProcessing; }
        set
        {
            if (_isProcessing == value)
                return;

            _isProcessing = value;

            if (!value)
            {
                if(_queryDisposable != null)
                    _queryDisposable.Dispose();
                _queryDisposable = null;
            }
            else
            {
                Observable
                    .Range(0,1)
                    .ObserveOn(Scheduler.ThreadPool)
                    .Subscribe(GetFeedsSafe, OnError, OnComplete);

                _queryDisposable = Observable
                    .Interval(TimeSpan.FromMinutes(5))
                    .ObserveOn(Scheduler.ThreadPool)
                    .Subscribe(GetFeedsSafe, OnError, OnComplete);
            }
        }
    }

私はそれが非常にエレガントな解決策だとは思わないので、この効果を達成するためのより良い方法があるかどうか知りたいですか?

4

3 に答える 3

3

Observable を開始する直前に、Subscribe を自分で呼び出しませんか?

    Subscribe(GetFeeds, OnError, OnComplete);
    // Or perhaps, if you want it to be async,
    new TaskFactory().StartNew(()=>Subscribe(GetFeeds, OnError, OnComplete));

    _queryDisposable = Observable
        .Interval(TimeSpan.FromMinutes(5))
        .ObserveOn(Scheduler.ThreadPool)
        .Where(i => IsProcessing)     // IsProcessing is the bool value
        .Subscribe(GetFeeds, OnError, OnComplete);

編集: http://social.msdn.microsoft.com/Forums/sa/rx/thread/c4acaf34-3136-4206-a6f9-ef5afba74b2bからの純粋な Rx :

Observable.Interval(TimeSpan.FromMinutes(5))
        .StartWith(-1L)
        .ObserveOn(Scheduler.ThreadPool)
        .Where(i => IsProcessing)     // IsProcessing is the bool value
        .Subscribe(GetFeeds, OnError, OnComplete);
于 2012-06-25T14:40:38.563 に答える
2

シーケンスをすぐに開始し、特定の時間内に値を生成するには、次の 2 つのオプションがあります。

  1. Observable.Interval(TimeSpan.FromMinutes(5)).StartWith(-1)
  2. Observable.Timer(TimeSpan.FromMinutes(0), TimeSpan.FromMinutes(5))

次に、IsProcessing 値が false に設定されているときにタイマーをキャンセルし、true に戻ったときにシーケンスを再開したいとします。上記の 2 つの回答は、IsProcessing 値がいつ設定されているかに関係なく、5 分間隔で実行されます。IsProcessing=true を設定すると、シーケンスが開始されます。1 分後に IsProcessing=false を設定してから IsProcessing=true を設定すると、再度クエリを実行するまで 4 分間待つ必要があります。これはあなたが望むものではないと思いますか?

したがって、プロパティの変更によってこれがトリガーされるようにします。@SPFiredrake は、INPC を提案し、イベントを Observable シーケンスに変換するという優れた仕事をしています。これを行うのに役立つ小さなスニペットがたくさんあります。拡張メソッド PropertyChanges を使用すると仮定すると、この非常に単純なクエリを記述できます。

var isProcessingValues = this.PropertyChanges(x=>x.IsProcessing);
isProcessingValues
    .Where(isProcessing=>isProcessing)
    .SelectMany(_=> 
        Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(5))
                  .TakeUntil(isProcessingValues.Where(isProcessing=>!isProcessing))
    )
    .Select(_=>GetFeeds())  //What does GetFeeds actually return?
    .SubscribeOn(Scheduler.NewThread)
    .Subscribe(feedData=>Console.WriteLine(feedData), 
        ex=>Console.WriteLine (ex),
        ()=>Console.WriteLine (completed));

これをゆっくりとステップ実行します:

  1. IsProcessing プロパティが変更されたら、新しい値をシーケンス (isProcessingValues) にプッシュします。
  2. シーケンス値が true の場合、現在および 5 分ごとに値を生成するタイマー シーケンスを開始します。
  3. isProcessingValues シーケンスが false の値を生成する場合、タイマー シーケンスは停止する必要があります。
  4. タイマーが作動するたびに (IsProcess が true に設定されている場合、および true の場合は 5 分ごと)、GetFeeds を呼び出します。
  5. シーケンスが別のスレッドでサブスクライブされていることを確認してください (ブロックしないようにするため)。これが要件でない場合は削除してください。
  6. フィードからデータを取得し、それを使って何かをします。
于 2012-07-06T12:25:26.097 に答える
0

IsProcessing 変数で prop changed イベントを発生させ、それをリッスンできるようにすることを考えたことはありますか?

var processing = Observable
    .FromEventPattern<PropertyChangedEventArgs>(this, "PropertyChanged")
    .Where(tr => tr.EventArgs.Property == "IsProcessing" && ((Type)tr.Sender).IsProcessing);

_queryDisposable = Observable
    .Interval(TimeSpan.FromMinutes(5))
    .ObserveOn(Scheduler.ThreadPool)
    .And(processing) // Will only fire when both sequences have an available value.
    .Subscribe(GetFeeds, OnError, OnComplete);

これにより、処理中のオブザーバブルは一度に 1 つの値しか提供しないため (IsProcessing が に変更されるたびにtrue)、処理中の場合は 1 回だけ起動されるため、まだ処理中の場合に再度起動することを心配する必要はありません。 5分後。

于 2012-06-25T14:47:19.667 に答える