0

これはアカデミックな演習です。私はReactiveExtensionsを初めて使用し、テクノロジーに頭を悩ませようとしています。私は、円周率の連続する桁を返すIObservableを作成するという目標を設定しました(関係のない理由で、現時点で円周率に本当に興味があります)。Reactive Extensionsには、オブザーバブルを作成するための演算子が含まれています。それらが提供するガイダンスは、「独自のIObsevableを作成する必要はほとんどない」というものです。しかし、既成の演算子とメソッドを使用してこれを行う方法がわかりません。もう少し詳しく説明させてください。

Arctanのテイラー級数の展開を含むアルゴリズムを使用することを計画していました。円周率の次の桁を取得するために、シリーズのさらにいくつかの用語を拡張します。

したがって、級数展開を非同期で実行する必要があり、次の計算された桁をIObserverにスローすることがあります。明らかに、新しい桁ごとに計算を最初からやり直したくありません。

RXの組み込み演算子を使用してこの動作を実装する方法はありますか、それともIObservableを最初からコーディングする必要がありますか?どのような戦略がそれ自体を示唆していますか?

4

2 に答える 2

2

このような場合、最も簡単な方法はSubjectを使用することです。件名はIObservableとIObserverの両方であり、少し奇妙に聞こえますが、次のように使用できます。

class PiCalculator
{
    private readonly Subject<int> resultStream = new Subject<int>();

    public IObservable<int> ResultStream
    {
        get { return resultStream; }
    }

    public void Start()
    {
        // Whatever the algorithm actually is
        for (int i = 0; i < 1000; i++)
        {
            resultStream.OnNext(i);
        }
    }
}

したがって、アルゴリズム内でOnNextは、次の値を生成するたびにサブジェクトを呼び出すだけです。

次に、それを使用するには、次のようなものが必要です。

var piCalculator = new PiCalculator();
piCalculator.ResultStream.Subscribe(n => Console.WriteLine((n)));
piCalculator.Start();
于 2012-06-21T19:29:13.020 に答える
1

最も簡単な方法は、を作成してEnumerableから変換することです。

IEnumerable<int> Pi()
{
    // algorithm here
    for (int i = 0; i < 1000; i++)
    {
        yield return i;
    }
}

使用法(コールドオブザーバブルの場合、つまり、すべての新しい「サブスクリプション」が最初からPiの作成を開始します):

var cold = Pi().ToObservable(Scheduler.ThreadPool);
cold.Take(5).Subscribe(Console.WriteLine);

あなたがそれを作りたいならhot(誰もが同じ基礎となる計算を共有します)、あなたはただこれをすることができます:

var hot = cold.Publish().RefCount();

これにより、最初のサブスクライバーの後に計算が開始され、すべてのサブスクライバーが切断されたときに計算が停止します。簡単なテストは次のとおりです。

hot.Subscribe(p => Console.WriteLine("hot1: " + p));
Thread.Sleep(5);    
hot.Subscribe(p => Console.WriteLine("hot2: " + p));    

これはhot1、少しの間だけ印刷し、しばらくhot2待ってから参加しますが、同じ番号を印刷することを示しているはずです。これがで行われた場合cold、2つのサブスクリプションはそれぞれ0から始まります。

于 2012-06-21T22:17:10.590 に答える