3

次のストリームを考えてみましょう

  SomeState state = new SomeState().

 _refreshFiberStream =
    Stream()
    .SubscribeOn(new EventLoopScheduler()) 
    .Select(DoCalc)
    .ObserveOn(DispatcherScheduler.Current)
    .Subscribe(Update);

DoCalc メソッドは入力に射影し、「状態」を消費します。結果の出力は、「状態」を変更する Update メソッドに渡されます。新しいイベントが発生した場合は、前のイベントから最後に更新された状態に基づいて動作し、それに基づいてプロジェクトを実行する必要があります。

イベントが常に順番に実行される方法を探しています。たとえば、3 つのイベントがある場合、それらが DoCalc、Update に続いて DoCalc、Update に続いて DoCalc、Update で実行される方法を探しています。

代わりに、DoCalc、DoCalc、Update、Update、DoCalc、Update が表示されます。つまり、順番に実行されることはありません。

Rxでそれを強制する方法はありますか

4

1 に答える 1

2

一方では順番に実行する必要があることと、他方では別のスレッドにディスパッチすることの間に競合が見られます。私の提案は、Update次の 2 つの部分に分割することです。

  1. 順番に実行する必要がある部分 (更新)
  2. 発送が必要な部品 (Dispatch)

次に、ディスパッチャーDo(Update)で順番に呼び出すことができます。Subscribe(Dispatch)

var result =
    Stream()
        .SubscribeOn(new EventLoopScheduler())
        .Select(DoCalc)
        .Do(Update)
        .ObserveOn(DispatcherScheduler.Current)
        .Subscribe(Dispatch);

結果のシーケンスは次のようになります (「Dispatch n」呼び出しは、「Update n」の後にいつでも発生する可能性があります)。

    を選択
    アップデート
    bを選択
    更新b
    派遣する
    派遣b

ManualResetEvent別の方法としては、次の DoCalc は Update が発生した後にのみ続行できることを示すa を使用することになると思います。ManualResetEvent.WaitOneこれは、DoCalc とManualResetEvent.SetUpdateに追加することで実行できます。

private ManualResetEvent _wait = new ManualResetEvent(true);

private string DoCalc(string input)
{
    _wait.WaitOne();
    Console.WriteLine("Selected {0}", input);
    _wait.Reset();
    return input;
}

private void Update(string input)
{
    Console.WriteLine("Update {0}", input);
    _wait.Set();
}

この2番目のアプローチは「機能します」が、このようなスレッドブロックは私を不安にさせます-リアクティブプログラミングとは異なる目的で機能するようです。そしてもちろん、同様に、可能であれば状態の導入を避けるのが最善です。

于 2013-10-04T22:13:02.887 に答える