Nach dem Lesen der Erklärung für warum
%Vor%wird nie abgeschlossen, aber
%Vor% funktioniert wie erwartet. Ich bin immer noch verwirrt und ich kann nicht sagen, warum currentThread
tatsächlich das Problem löst. Kann jemand eine klare Erklärung geben?
Der Link von Ned Stoyanov in den Kommentaren zur Verfügung gestellt hat eine großartige Erklärung von Dave Sexton.
Ich werde versuchen, es ein bisschen anders zu illustrieren. Nehmen Sie dieses Beispiel, in dem ein rekursiver Aufruf in der RecursiveTest-Methode auftritt.
%Vor%Sie können leicht sehen, dass das auf unbestimmte Zeit rekurriert (bis zu einer StackOverflowException), weil _isDone niemals auf true gesetzt wird. Es ist ein übermäßig vereinfachtes Beispiel, aber es ist im Grunde, was mit Ihrem ersten Beispiel passiert.
Dies ist die Erklärung von Dave Sexton, um zu beschreiben, was in Ihrem ersten Beispiel passiert.
Standardmäßig verwendet Return den ImmediateScheduler, um OnNext (1) aufzurufen OnCompleted (). Wiederholen führt keine Nebenläufigkeit ein, also sieht es OnCompleted sofort und dann sofort erneut zu Return. Da es in Return kein Trampolin gibt, wiederholt sich dieses Muster, Blockieren des aktuellen Threads auf unbestimmte Zeit. Calling Abonnieren Sie dies Observable kehrt nie zurück.
Mit anderen Worten, wegen der Endlosschleife der Reentrancy wird der anfängliche Fluss nie vollständig abgeschlossen. Wir brauchen also einen Weg, um den anfänglichen Fluss ohne Wiedereintritt zu vervollständigen.
Gehen wir zurück zu meinem Beispiel RecursiveTest oben in diesem Beitrag. Was wäre die Lösung, um eine unendliche Rekursion zu vermeiden? Wir würden die RecursiveMethod benötigen, um ihren Ablauf abzuschließen, bevor die RecursiveMethod erneut ausgeführt wird. Eine Möglichkeit, dies zu tun, besteht darin, eine Warteschlange zu erstellen und den Aufruf der RecursiveMethod wie folgt einzuordnen:
%Vor%Auf diese Weise würde der anfängliche Fluss abgeschlossen werden, _isDone würde auf "true" gesetzt werden, und wenn der nächste Aufruf von RecursiveMethod ausgeführt wird, wird nichts mehr ausgeführt, wodurch die unendliche Rekursion vermieden wird. Und das ist, was das Scheduler.CurrentThread Ihrem zweiten Beispiel tun wird.
Sehen wir uns an, wie Dave Sexton erklärt, wie Ihr zweites Beispiel funktioniert:
Hier verwendet Return den CurrentTheadScheduler, um OnNext (1) aufzurufen OnCompleted (). Wiederholen führt keine Nebenläufigkeit ein, also sieht es OnCompleted sofort und dann sofort wieder zu Return; Dieses zweite Abonnement von "Return" terminiert sein (inneres) Aktionen auf dem Trampolin, weil es immer noch auf der OnCompleted Callback von der ersten geplanten (äußeren) Aktion, also der Wiederholung tritt nicht sofort auf. Dies ermöglicht Repeat, um a zurückzugeben Einweg zu Take, die schließlich OnCompleted aufruft, storniert die Wiederholung, indem Sie Repeat und schließlich den Aufruf von Subscribe disponieren zurück.
Wieder wurde mein Beispiel wirklich vereinfacht, um es einfach zu verstehen und es ist nicht genau so, wie es funktioniert. Hier sind Sie kann sehen, wie der Scheduler wirklich funktioniert. Es verwendet, was sie eine Trampoline nennen, die im Grunde eine Warteschlange ist, die sicherstellt, dass es keine Wiedereintrittsrufe gibt. Alle Aufrufe werden daher nacheinander auf demselben Thread serialisiert. Auf diese Weise kann der anfängliche Fluss vervollständigt werden, der die unendliche Wiedereintrittsschleife vermeidet.
Ich hoffe, das ist ein bisschen klarer:)
Tags und Links system.reactive