Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 观察和订阅-工作正在进行的地方_C#_.net_System.reactive - Fatal编程技术网

C# 观察和订阅-工作正在进行的地方

C# 观察和订阅-工作正在进行的地方,c#,.net,system.reactive,C#,.net,System.reactive,根据阅读此问题: ObserveOn设置执行Subscribe处理程序中代码的位置: stream.Subscribe(=>{//这里的代码}) SubscribeOn方法设置在哪个线程上完成流的设置 我被引导去理解,如果没有显式地设置它们,那么就使用TaskPool 现在我的问题是,假设我这样做: Observable.Interval(new Timespan(0, 0, 1)) .Where(t => predicate(t)) .Select

根据阅读此问题:

ObserveOn
设置执行
Subscribe
处理程序中代码的位置:

stream.Subscribe(=>{//这里的代码})

SubscribeOn
方法设置在哪个线程上完成流的设置

我被引导去理解,如果没有显式地设置它们,那么就使用TaskPool

现在我的问题是,假设我这样做:

Observable.Interval(new Timespan(0, 0, 1))
          .Where(t => predicate(t))
          .SelectMany(t => lots_of(t))
          .ObserveOnDispatcher()
          .Subscribe(t => some_action(t));
Calling from Thread: 1
Timer: Observable obtained on Thread: 1
ObserveOn: Observable obtained on Thread: 1
ObserveOn: Subscribed to on Thread: 1
Timer: Subscribed to on Thread: 1
Timer: Subscription completed.
ObserveOn: Subscription completed.
Subscribe returned
Blocking the dispatcher
Timer: OnNext(0) on Thread: 2
Timer: OnCompleted() on Thread: 2
Unblocked
ObserveOn: OnNext(0) on Thread: 1
ObserveOn: OnCompleted() on Thread: 1

鉴于调度程序上正在执行一些动作,执行的
Where
谓词和
SelectMany
lots\u
在哪里

总结
  • subscribebeon
    拦截对
    IObservable
    的单个方法的调用,即
    Subscribe
    ,以及对
    Subscribe
    返回的
    IDisposable
    句柄上的
    Dispose
    的调用
  • ObserveOn
    拦截对
    IObserver
    方法的调用,这些方法是
    OnNext
    OnCompleted
    OnError
  • 这两种方法都会导致在指定的计划程序上进行相应的调用
分析与演示 声明

ObserveOn设置订阅处理程序中代码的位置 执行:

这比帮助更令人困惑。您所指的“订阅处理程序”实际上是一个
OnNext
处理程序。请记住,
IObservable
Subscribe
方法接受具有
OnNext
OnCompleted
OnError
方法的
IObserver
,但扩展方法提供了方便的重载,可以接受lambda并为您构建
IObserver
实现

让我用这个词吧;我认为“Subscribe handler”是在调用
Subscribe
时调用的可观察对象中的代码。这样,上面的描述更接近于
SubscribeOn
的目的

订阅
SubscribeOn
导致可观察对象的
Subscribe
方法在指定的计划程序或上下文上异步执行。当您不想从正在运行的任何线程对一个可观察的对象调用
Subscribe
方法时,您可以使用它,这通常是因为它可以长期运行,并且您不想阻止调用线程

当您调用Subscribe
时,您调用的是一个可观察对象,它可能是一长串可观察对象的一部分。只有
SubscribeOn
应用于其影响的可观察值。现在可能会出现这样的情况,即链中的所有可观察对象将立即在同一线程上订阅,但情况并非如此。例如,考虑
Concat
,它只在前一个流完成后订阅每个后续流,通常这将发生在前一个流调用
OnCompleted
的任何线程上

因此,
SubscribeOn
位于对
Subscribe
的调用和要订阅的可观察对象之间,拦截调用并使其异步

它还影响订阅的处理
Subscribe
返回用于取消订阅的
IDisposable
句柄
SubscribeOn
确保在提供的计划程序上计划调用
Dispose

当试图理解
SubscribeOn
所做的事情时,一个常见的混淆点是,可观察对象的
Subscribe
处理程序可能会在同一线程上调用
OnNext
OnCompleted
OnError
。但是,其目的不是影响这些通话。流在
Subscribe
方法返回之前完成并不罕见<代码>可观察。例如,Return
执行此操作。让我们看一下。

如果使用我编写的方法并运行以下代码:

Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Return(1).Spy("Return");
source.Subscribe();
Console.WriteLine("Subscribe returned");
您将获得此输出(当然线程id可能会有所不同):

您可以看到整个订阅处理程序在同一个线程上运行,并在返回之前完成

让我们使用
SubscribeOn
异步运行它。我们将监视
返回
可观察和
订阅
可观察:

Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Return(1).Spy("Return");
source.SubscribeOn(Scheduler.Default).Spy("SubscribeOn").Subscribe();
Console.WriteLine("Subscribe returned");
此输出(由我添加的行号):

01-主要方法在线程1上运行

02-在调用线程上评估可观察的
返回。我们只是在这里得到了
IObservable
,还没有任何订阅

03-在调用线程上评估可观察的
SubscribeOn

04-现在我们最后调用
Subscribe
方法
subscribebeon

05-Subscribe
方法异步完成

06-。。。线程1返回到main方法这是SubscribeOn的实际效果

07-同时,
SubscribeOn
在默认调度程序上安排了一个调用,以
Return
。这里它是在线程2上接收的

08-正如
Return
所做的那样,它在
Subscribe
线程上调用
OnNext

09-而
SubscribeOn
现在只是一个过客

10,11-与未完成的<代码>相同

12-最后一个
返回
订阅处理程序完成

希望这能澄清订阅的目的和效果

观察 如果将
SubscribeOn
视为将调用传递给不同线程的
Subscribe
方法的拦截器,则
ObserveOn
执行相同的任务,但
01 Calling from Thread: 1
02 Return: Observable obtained on Thread: 1
03 SubscribeOn: Observable obtained on Thread: 1
04 SubscribeOn: Subscribed to on Thread: 1
05 SubscribeOn: Subscription completed.
06 Subscribe returned
07 Return: Subscribed to on Thread: 2
08 Return: OnNext(1) on Thread: 2
09 SubscribeOn: OnNext(1) on Thread: 2
10 Return: OnCompleted() on Thread: 2
11 SubscribeOn: OnCompleted() on Thread: 2
12 Return: Subscription completed.
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Return(1).Spy("Return");
source.Subscribe();
Console.WriteLine("Subscribe returned");
Calling from Thread: 1
Return: Observable obtained on Thread: 1
Return: Subscribed to on Thread: 1
Return: OnNext(1) on Thread: 1
Return: OnCompleted() on Thread: 1
Return: Subscription completed.
Subscribe returned
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Return(1).Spy("Return");
source.ObserveOn(Scheduler.Default).Spy("ObserveOn").Subscribe();
Console.WriteLine("Subscribe returned");
01 Calling from Thread: 1
02 Return: Observable obtained on Thread: 1
03 ObserveOn: Observable obtained on Thread: 1
04 ObserveOn: Subscribed to on Thread: 1
05 Return: Subscribed to on Thread: 1
06 Return: OnNext(1) on Thread: 1
07 ObserveOn: OnNext(1) on Thread: 2
08 Return: OnCompleted() on Thread: 1
09 Return: Subscription completed.
10 ObserveOn: Subscription completed.
11 Subscribe returned
12 ObserveOn: OnCompleted() on Thread: 2
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Timer(TimeSpan.FromSeconds(1)).Spy("Timer");
source.Subscribe();
Console.WriteLine("Subscribe returned");
Calling from Thread: 1
Timer: Observable obtained on Thread: 1
Timer: Subscribed to on Thread: 1
Timer: Subscription completed.
Subscribe returned
Timer: OnNext(0) on Thread: 2
Timer: OnCompleted() on Thread: 2
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Timer(TimeSpan.FromSeconds(1)).Spy("Timer");
source.SubscribeOn(NewThreadScheduler.Default).Spy("SubscribeOn").Subscribe();
Console.WriteLine("Subscribe returned");
Calling from Thread: 1
Timer: Observable obtained on Thread: 1
SubscribeOn: Observable obtained on Thread: 1
SubscribeOn: Subscribed to on Thread: 1
SubscribeOn: Subscription completed.
Subscribe returned
Timer: Subscribed to on Thread: 2
Timer: Subscription completed.
Timer: OnNext(0) on Thread: 3
SubscribeOn: OnNext(0) on Thread: 3
Timer: OnCompleted() on Thread: 3
SubscribeOn: OnCompleted() on Thread: 3
var dispatcher = Dispatcher.CurrentDispatcher;
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Timer(TimeSpan.FromSeconds(1)).Spy("Timer");
source.ObserveOnDispatcher().Spy("ObserveOn").Subscribe();
Console.WriteLine("Subscribe returned");
Calling from Thread: 1
Timer: Observable obtained on Thread: 1
ObserveOn: Observable obtained on Thread: 1
ObserveOn: Subscribed to on Thread: 1
Timer: Subscribed to on Thread: 1
Timer: Subscription completed.
ObserveOn: Subscription completed.
Subscribe returned
Timer: OnNext(0) on Thread: 2
ObserveOn: OnNext(0) on Thread: 1
Timer: OnCompleted() on Thread: 2
ObserveOn: OnCompleted() on Thread: 1
var dispatcher = Dispatcher.CurrentDispatcher;
Console.WriteLine("Calling from Thread: " + Thread.CurrentThread.ManagedThreadId);
var source = Observable.Timer(TimeSpan.FromSeconds(1)).Spy("Timer");
source.ObserveOnDispatcher().Spy("ObserveOn").Subscribe();
Console.WriteLine("Subscribe returned");
Console.WriteLine("Blocking the dispatcher");
Thread.Sleep(2000);
Console.WriteLine("Unblocked");
Calling from Thread: 1
Timer: Observable obtained on Thread: 1
ObserveOn: Observable obtained on Thread: 1
ObserveOn: Subscribed to on Thread: 1
Timer: Subscribed to on Thread: 1
Timer: Subscription completed.
ObserveOn: Subscription completed.
Subscribe returned
Blocking the dispatcher
Timer: OnNext(0) on Thread: 2
Timer: OnCompleted() on Thread: 2
Unblocked
ObserveOn: OnNext(0) on Thread: 1
ObserveOn: OnCompleted() on Thread: 1
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();
        }
    }
}
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; }
        }
    }
}