我正在尝试从两个数组(IObservable<T>
s)创建IEnumerable
。我试图避免显式迭代数组并调用observer.OnNext
。我遇到了Observable.Subscribe扩展方法,乍一看似乎是我需要的方法。但是,它没有像我预期的那样工作,我不知道为什么。
以下代码是一个示例:
class Program
{
static void Main(string[] args)
{
var observable = Observable.Create<char>(observer =>
{
var firstBytes = new[] {'A'};
var secondBytes = new[] {'Z', 'Y'};
firstBytes.Subscribe(observer);
secondBytes.Subscribe(observer);
return Disposable.Empty;
}
);
observable.Subscribe(b => Console.Write(b));
}
}
这是“AZ”的输出,而不是我预期的“AZY”。现在,如果我在secondBytes
之前订阅firstBytes
,则输出为“ZAY”!这似乎表明它正在逐步枚举两个数组 - 哪种解释了“AZ”输出。
无论如何,我完全不知道为什么它会像这样,并且会欣赏人们可能提供的任何洞察力。
答案 0 :(得分:2)
因为您订阅了两个 observable,而不是单个observable,它是两个observable的串联,所以有两个可能的源可以调用观察者的OnComplete
方法。由于第一个数组较短,因此在第一个项目发出后完成,观察者取消订阅,因为它已收到完成通知。
正确的方法是将两个序列组合成一个序列,然后订阅:
var observable = Observable.Create<char>(observer =>
{
var firstBytes = new[] { 'A' };
var secondBytes = new[] { 'Z', 'Y' };
return firstBytes.Concat(secondBytes).Subscribe(observer);
});
observable.Subscribe(Console.Write);
答案 1 :(得分:2)
锁定步骤迭代行为的原因可以通过Observable.Subscribe(IEnumerable source)的实现来解释,"recursive" algorithm使用{{3}},它通过在调度程序操作中调用e.MoveNext
来工作。如果成功,则发出该值,然后将新的调度程序操作排队以从可枚举中读取下一个值。
当您订阅两个枚举但没有为订阅指定任何特定的调度程序时,默认的迭代调度程序将用于这些操作(由SchedulerDefaults.Iteration
定义),默认情况下在当前线程上运行。这意味着枚举操作将排队等待当前订阅操作完成后运行。这会导致枚举操作交错 - 类似这样
观察者在步骤5接收OnCompleted()通知,因此忽略剩余的secondBytes枚举步骤。如果您已经退回订购的一次性用品,则第二次枚举将在此时被取消。