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"));