C# 如何使IObservable.ToEnumerable在返回之前不阻塞/不消耗整个源?

C# 如何使IObservable.ToEnumerable在返回之前不阻塞/不消耗整个源?,c#,system.reactive,C#,System.reactive,我怎样才能在回来之前不完成考试呢 IObservable<string> str = test() .ToObservable() .Finally(() => Console.WriteLine("obs done")); int i = 0; foreach (string s in str.ToEnumerable()) { if (i++ > 5) { Console.Wri

我怎样才能在回来之前不完成考试呢

 IObservable<string> str =
        test()
        .ToObservable()
        .Finally(() => Console.WriteLine("obs done"));

 int i = 0;
 foreach (string s in str.ToEnumerable())
 {
    if (i++ > 5)
    {
        Console.WriteLine("break");
        break;
    }
    Console.WriteLine(s);
 }

 IEnumerable<string> test()
 {
    for (int i = 0; i < 10; i++)
    {
        Thread.Sleep(500);
        Console.WriteLine($"called {i+1} a");
        yield return "a";
        Console.WriteLine($"called {i+1} b");
        yield return "b";
        Console.WriteLine($"called {i+1} c");
        yield return "c";
    }
 }
但我希望它能打印出这样的东西

 called 1 a
 a
 called 1 b
 b
 called 1 c
 c
 called 2 a
 a
 called 2 b
 b
 called 2 c
 c
 break
 obs done
 here
编辑: 当我最初不使用IEnumerable来生成数据,并添加一个cancellationtoken时,它就可以工作了,这可能与通过迭代创建的枚举数的处理有关。ToEnumerable

 IObservable<string> str =
        test2()    
        .Finally(() => Console.WriteLine("obs done"));

 IObservable<string> test2()
 {
    return Observable.Create<string>(async (observer, cancel) =>
    {
        for (int i = 0; i < 10 && !cancel.IsCancellationRequested; i++)
        {
            await Task.Delay(500);
            Console.WriteLine($"called {i + 1} a");
            observer.OnNext("a");
            Console.WriteLine($"called {i + 1} b");
            observer.OnNext("b");
            Console.WriteLine($"called {i + 1} c");
            observer.OnNext("c");
        }
    });
 }

类似于此的内容可能更接近您要查找的内容:

    var str =
        test()
            .ToObservable()
            .Finally(() => Console.WriteLine("obs done"));
    str.Take(5).Subscribe(
        Console.WriteLine, 
        () => Console.WriteLine("break"));
更新:
好吧,我明白你的意思了。我认为您在原始示例中看到的是ToObservable的默认调度程序实际上是CurrentThread。这会导致迭代循环阻塞当前线程,直到它遍历整个序列。您可以为ToObservable eg Default提供不同的计划程序,这与第二个示例相当。

我不知道您想做什么。您使序列可观察,从不订阅它,然后再次使其可枚举以遍历结果。要么拿出TooObservable和Finally,要么订阅Observable。其中一个可能会让你更接近你想要的。或者分享更多关于您试图完成的内容的信息。@lesscode我用一个工作示例编辑过,所以我想我的问题是,如果test2被释放,为什么原始测试不被释放?好的,请参阅更新的答案谢谢!我想我现在明白了。通过使用.ToObservableScheduler.Default,它按照最初的预期工作。
    var str =
        test()
            .ToObservable()
            .Finally(() => Console.WriteLine("obs done"));
    str.Take(5).Subscribe(
        Console.WriteLine, 
        () => Console.WriteLine("break"));