.net system.reactive

.net - ¿Cuál es la diferencia entre SubscribeOn y ObserveOn?



system.reactive (3)

Acabo de descubrir SubscribeOn , lo que me hace preguntarme si debería usar eso en lugar de ObserveOn . Google me llevó here y here , pero ninguno me ha ayudado a asimilar la diferencia: parece increíblemente sutil.

(En mi contexto, tengo eventos ''próximos'' en un hilo no gui, y tengo que cambiar a un hilo de interfaz gráfica de usuario antes de usar los datos del evento para actualizar los controles).


Básicamente, las diferencias radican en que se suscriba Forzar que toda la canalización sea procesada por otro hilo, pero con el observador. Solo los pasos en su canalización después de que observerOn se ejecute en otro hilo, solo después de que lo configure se ejecutará en otro hilo.

Observable.just(1) .map ---> executed in Main thread .filter ---> executed in Main thread .subscribeOn(Scheduers.io) .subscribe()

Todos los pasos de la tubería se ejecutarán en otro hilo.

Observable.just(1) .map ---> executed in Main thread .filter ---> executed in Main thread .observerOn(Scheduers.io) .map ---> executed in New thread .filter ---> executed in New thread .subscribe()


Hace un tiempo tuve un problema similar y le hice this pregunta al respecto. Creo que las respuestas (incluidos los comentarios) responderán a su pregunta. Para resumir:

  • Si desea actualizar los controles en un hilo de interfaz ObserveOn , use ObserveOn . Si hace referencia a System.Reactive.Windows.Forms.dll obtendrá el .ObserveOn(form) que es útil.
  • SubscribeOn controla el hilo en el que se produce la llamada real para suscribirse. El problema que se resuelve aquí es que WinForms y WPF arrojarán excepciones si agrega manejadores de eventos de múltiples hilos diferentes.

Además, this publicación fue muy útil para descubrir la relación entre ObserveOn y SubscribeOn .


Me ayudó a entender esto pensando en SubscribeOn como establecer el hilo "pasado" por la cadena y ObserveOn como establecer el hilo "pasado" por la cadena.

El siguiente código usa hilos con nombre con los que puedes jugar.

Thread.CurrentThread.Name = "Main"; IScheduler thread1 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread1" }); IScheduler thread2 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread2" }); Observable.Create<int>(o => { Console.WriteLine("Subscribing on " + Thread.CurrentThread.Name); o.OnNext(1); return Disposable.Create(() => {}); }) .SubscribeOn(thread1) .ObserveOn(thread2) .Subscribe(x => Console.WriteLine("Observing ''" + x + "'' on " + Thread.CurrentThread.Name));

El resultado de lo anterior es:

Subscribing on Thread1 Observing 1 on Thread2

También es interesante ver que cuando comenta la línea SubscribeOn , la salida es:

Subscribing on Main Observing 1 on Thread2

Porque de manera predeterminada, la suscripción "desaparece" cualquiera que sea el hilo que se estaba ejecutando ( Main aquí). Luego, ObserveOn "pasa" a Thread2 .

Si en lugar de comentar la línea ObserveOn , la salida es:

Subscribing on Thread1 Observing 1 on Thread1

Porque "pasamos" la suscripción en Thread1 , y por defecto este mismo hilo se "pasa" y se usa para ejecutar la observación.