gpt4 book ai didi

system.reactive - 调度程序 : Immediate vs. 当前线程

转载 作者:行者123 更新时间:2023-12-04 04:16:48 31 4
gpt4 key购买 nike

看完explanation为什么

Observable.Return(5)
.Repeat()
.Take(1)

永远不会完成,但是
Observable.Return(5, Scheduler.CurrentThread)
.Repeat()
.Take(1)

按预期工作。我仍然很困惑,我不知道为什么 currentThread实际上解决了问题。有人能给出明确的解释吗?

最佳答案

link Ned Stoyanov 在上面的评论中提供了 Dave Sexton 的很好的解释。
我将尝试以不同的方式来说明它。以 RecursiveMethod 中发生递归调用为例。

public class RecursiveTest()
{
private bool _isDone;

public void RecursiveMethod()
{
if (!_isDone)
{
RecursiveMethod();

// Never gets here...
_isDone = true;
}
}
}
您可以很容易地看到这将无限递归(直到出现 StackOverflowException),因为 _isDone 永远不会被设置为 true。这是一个过于简化的示例,但基本上就是您的第一个示例所发生的情况。
这是 Dave Sexton 的解释,用于描述您的第一个示例中发生的情况。

By default, Return uses the ImmediateScheduler to call OnNext(1) thenOnCompleted(). Repeat does not introduce any concurrency, so it seesOnCompleted immediately and then immediately resubscribes to Return.Because there's no trampoline in Return, this pattern repeats itself,blocking the current thread indefinitely. Calling Subscribe on thisobservable never returns.


换句话说,由于可重入的无限循环,初始流程永远不会完全完成。所以我们需要一种方法来完成初始流程而无需重入。
让我们回到本文上面的 RecursiveTest 示例,避免无限递归的解决方案是什么?在再次执行 RecursiveMethod 之前,我们需要 RecursiveMethod 完成其流程。一种方法是创建一个队列并将对 RecursiveMethod 的调用加入队列,如下所示:
public void RecursiveMethod()
{
if (!_isDone)
{
Enqueue(RecursiveMethod);
_isDone = true;
}
}
这样,初始流程将完成,_isDone 将被设置为 true,并且在执行下一次对 RecursiveMethod 的调用时,将不再执行任何操作,避免了无限递归。这几乎是 Scheduler.CurrentThread 将对您的第二个示例执行的操作。
让我们看看 Dave Sexton 如何解释您的第二个示例的工作原理:

Here, Return is using the CurrentTheadScheduler to call OnNext(1) thenOnCompleted(). Repeat does not introduce any concurrency, so it seesOnCompleted immediately and then immediately resubscribes to Return;however, this second subscription to Return schedules its (inner)actions on the trampoline because it's still executing on theOnCompleted callback from the first scheduled (outer) action, thus therepetition does not occur immediately. This allows Repeat to return adisposable to Take, which eventually calls OnCompleted, cancels therepetition by disposing Repeat, and ultimately the call from Subscribereturns.


同样,我的示例确实经过简化以使其易于理解,并且它的工作原理并不完全正确。 Here you can see调度程序是如何工作的。它使用他们所谓的 Trampoline,它基本上是一个队列,可确保没有可重入调用。因此,所有调用都在同一线程上一个接一个地序列化。通过这样做,可以完成初始流程,避免无限重入循环。
希望这更清楚一点:)

关于system.reactive - 调度程序 : Immediate vs. 当前线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31015278/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com