11

私は現在、RX .NET との並行性に頭を悩ませようとしていて、何かに混乱しています。4つの比較的遅いタスクを並行して実行したいので、 「各作業単位を個別のスレッドでスケジュールするオブジェクトを表す」NewThreadScheduler.Defaultのが良いと思いました。.

これが私のセットアップコードです:

    static void Test()
    {
        Console.WriteLine("Starting. Thread {0}", Thread.CurrentThread.ManagedThreadId);

        var query = Enumerable.Range(1, 4);
        var obsQuery = query.ToObservable(NewThreadScheduler.Default);
        obsQuery.Subscribe(DoWork, Done);

        Console.WriteLine("Last line. Thread {0}", Thread.CurrentThread.ManagedThreadId);
    }

    static void DoWork(int i)
    {
        Thread.Sleep(500);
        Console.WriteLine("{0} Thread {1}", i, Thread.CurrentThread.ManagedThreadId);
    }

    static void Done()
    {
        Console.WriteLine("Done. Thread {0}", Thread.CurrentThread.ManagedThreadId);
    }

「XスレッドY」は毎回異なるスレッドIDを出力すると想定しましたが、実際の出力は次のとおりです。

Starting. Thread 1
Last line. Thread 1
1 Thread 3
2 Thread 3
3 Thread 3
4 Thread 3
Done. Thread 3

すべての作業は、同じ新しいスレッドで順番に実行されますが、これは私が期待していたものではありません。

何かが欠けていると思いますが、何がわかりません。

4

1 に答える 1

13

監視可能なクエリには、Queryそれ自体と の2 つの部分がありますSubscription。(これは、ObserveOn オペレーターと SubscribeOn オペレーターの違いでもあります。)

あなたQuery

Enumerable
    .Range(1, 4)
    .ToObservable(NewThreadScheduler.Default);

これにより、そのシステムのデフォルトでを生成するオブザーバブルが作成されNewThreadSchedulerます。

あなたのサブスクリプションは

obsQuery.Subscribe(DoWork, Done);

これは、 によって生成された値ごとに実行さDoWorkれ、が呼び出しで終了したときに実行されます。サブスクリプションが実行されるスレッドと同じスレッドでクエリのすべての値が生成される場合、実際には、サブスクライブメソッドの関数がどのスレッドで呼び出されるかについての保証はないと思います。彼らはまた、すべてのサブスクリプション呼び出しが同じスレッドで行われるようにしているようです。これは、多くの一般的なマルチスレッドエラーを取り除くために行われる可能性が最も高い.QueryDoneQueryOnComplete

したがって、2 つの問題があります。1 つはロギングに関するものですQuery

Enumerable
    .Range(1, 4)
    .Do(x => Console.WriteLine("Query Value {0} produced on Thread {1}", x, Thread.CurrentThread.ManagedThreadId);
    .ToObservable(NewThreadScheduler.Default);

新しいスレッドで生成された各値が表示されます。

もう 1 つの問題は、Rx の意図と設計の 1 つです。は長時間実行されるプロセスであり、は結果を処理する短いメソッドです。長時間実行される関数を Rx Observable として実行する場合、最良のオプションはObservable.ToAsyncを使用することです。QuerySubscription

于 2013-07-21T18:53:16.233 に答える