【问题标题】:Reactive Extensions: Why does this exit immediately?反应式扩展:为什么会立即退出?
【发布时间】:2013-08-24 06:10:51
【问题描述】:

我正在阅读IntroToRx,但示例代码有点问题。这是我的代码的总和:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LearningReactiveExtensions
{
  public class Program
  {
    static void Main(string[] args)
    {
        var observable = Observable.Interval(TimeSpan.FromSeconds(5));
        observable.Subscribe(
          Console.WriteLine, 
          () => Console.WriteLine("Completed")
        );
        Console.WriteLine("Done");
        Console.ReadKey();
    }

  }
}

如果我对这本书的理解正确,这应该会向控制台写入一个数字序列,每五秒一次永远,因为我从来没有Dispose()这个序列。

但是,当我运行代码时,我得到的只是最后的“完成”。没有数字,没有“完成”,只有“完成”。

我在这里做错了什么?

【问题讨论】:

    标签: system.reactive reactive-programming


    【解决方案1】:

    我假设您没有耐心等待 5 秒钟,否则您会看到代码正在运行。

    要记住Rx 的主要思想是Observable.Subscribe 几乎会立即将控制权返回给调用方法。换句话说,Observable.Subscribe 在结果产生之前不会阻塞。因此对Console.WriteLine 的调用将仅在五秒后被调用。

    【讨论】:

    • 不是我缺乏耐心;相反,我假设除非序列完成,否则“完成”永远不会显示,例如从未在示例中。我的理解存在根本缺陷。
    • 我有一阵子担心我用 Done 子句和 Completed 举了一个例子。如果你把“完成”这个词换成“订阅”,那么你的程序会更准确。理想情况下,还要捕获订阅,然后在 ReadKey() 之后将其处理掉。
    【解决方案2】:

    你需要一些方法让主线程等待你正在做的事情。如果您愿意,可以使用信号量

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reactive.Disposables;
    using System.Reactive.Linq;
    using System.Reactive.Subjects;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace LearningReactiveExtensions
    {
      public class Program
      {
        static void Main(string[] args)
        {
             SemaphoreSlim ss = new SemaphoreSlim(1);
            var observable = Observable.Interval(TimeSpan.FromSeconds(5));
            observable.Subscribe(
              Console.WriteLine, 
              () => {
                   Console.WriteLine("Completed");
                   ss.Release();
              }
            );
            ss.Wait();
            Console.WriteLine("Done");
            Console.ReadKey();
        }
    
      }
    }
    

    虽然在这种情况下写起来可能更好

      static void Main(string[] args)
       {
            SemaphoreSlim ss = new SemaphoreSlim(1);
            Observable.Interval(TimeSpan.FromSeconds(5)).Wait();
            Console.WriteLine("Completed");
            Console.WriteLine("Done");
            Console.ReadKey();
       }
    

    【讨论】:

    • 我认为您不应该在这样一个简单的示例中使用原始等待句柄和 Rx。 IMO,这样做会破坏学习 Rx 的意义。
    • 你必须在 main 中使用等待。您不能将其标记为异步并使用等待。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 2020-11-05
    • 2015-04-18
    • 1970-01-01
    • 2022-07-08
    • 1970-01-01
    相关资源
    最近更新 更多