web-dev-qa-db-ja.com

ObserveOnとSubscribeOn-作業が行われている場所

この質問を読んだことに基づいて: SubscribeOnとObserveOnの違いは何ですか

ObserveOnは、コードがSubscribeハンドラーのどこに実行されるかを設定します。

stream.Subscribe(_ => { // this code here });

SubscribeOnメソッドは、ストリームのセットアップが行われるスレッドを設定します。

これらが明示的に設定されていない場合、TaskPoolが使用されることを理解するようになります。

私の質問は、次のようなことをすることです。

Observable.Interval(new Timespan(0, 0, 1)).Where(t => predicate(t)).SelectMany(t => lots_of(t)).ObserveOnDispatcher().Subscribe(t => some_action(t));

WherepredicateおよびSelectManylots_ofが実行されている場合、some_actionはディスパッチャで実行されていますか?

53
Cheetah

ジェームズの答えは非常に明確で包括的なものでした。しかし、それにもかかわらず、違いを説明しなければならないことに気づきました。

そのため、どのスケジューラーが呼び出されているかをグラフィカルに示すことができる非常にシンプルで愚かな例を作成しました。アクションをすぐに実行しますが、コンソールの色を変更するクラスMySchedulerを作成しました。

SubscribeOnスケジューラーからのテキスト出力は赤で出力され、ObserveOnスケジューラーからのテキスト出力は青で出力されます。

using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;

namespace SchedulerExample
{

    class Program
    {
        static void Main(string[] args)
        {
            var mydata = new[] {"A", "B", "C", "D", "E"};
            var observable = Observable.Create<string>(observer =>
                                            {
                                                Console.WriteLine("Observable.Create");
                                                return mydata.ToObservable().
                                                    Subscribe(observer);
                                            });

            observable.
                SubscribeOn(new MyScheduler(ConsoleColor.Red)).
                ObserveOn(new MyScheduler(ConsoleColor.Blue)).
                Subscribe(s => Console.WriteLine("OnNext {0}", s));

            Console.ReadKey();
        }
    }
}

この出力:

scheduler

また、MySchedulerの参照用(実際の使用には適していません):

using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;

namespace SchedulerExample
{
    class MyScheduler : IScheduler
    {
        private readonly ConsoleColor _colour;

        public MyScheduler(ConsoleColor colour)
        {
            _colour = colour;
        }

        public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
        {
            return Execute(state, action);
        }

        private IDisposable Execute<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
        {
            var tmp = Console.ForegroundColor;
            Console.ForegroundColor = _colour;
            action(this, state);
            Console.ForegroundColor = tmp;
            return Disposable.Empty;
        }

        public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
        {
            throw new NotImplementedException();
        }

        public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)
        {
            throw new NotImplementedException();
        }

        public DateTimeOffset Now
        {
            get { return DateTime.UtcNow; }
        }
    }
}
13
Dave Hillier

.SubcribeOn内のコードが実行されているスレッドを設定するために.Subscribeが使用されるとよく​​間違えます。ただし、パブリッシュとサブスクライブは陰陽のようなペアでなければならないことを覚えておいてください。 Subscribe's codeが実行される場所を設定するには、ObserveOnを使用します。 Observable's codeが実行された場所を設定するには、SubscribeOnを使用しました。または要約マントラ:where-whatSubscribe-ObserveObserve-Subscribe

0