Qual è la differenza tra SubscribeOn e ObserveOn

Ho appena scoperto SubscribeOn , il che mi chiede se dovrei usarlo al posto di ObserveOn . Google mi ha portato qui e qui , ma nessuno dei due mi ha aiutato a troncare la differenza: sembra incredibilmente sottile.

(Nel mio contesto, ho gli eventi “in arrivo” su un thread non-gui, e ho bisogno di passare a un thread GUI prima di usare i dati dell’evento per aggiornare i controlli).

Ho avuto un problema simile qualche tempo fa e ho fatto questa domanda al riguardo. Penso che le risposte (compresi i commenti) risponderanno alla tua domanda. Riassumere:

  • Se si desidera aggiornare i controlli su un thread GUI, utilizzare ObserveOn . Se si fa riferimento a System.Reactive.Windows.Forms.dll si ottiene il .ObserveOn(form) che è utile.
  • SubscribeOn controlla il thread su cui avviene la chiamata effettiva per iscriversi. Il problema risolto qui è che WinForms e WPF generano eccezioni se si aggiungono gestori di eventi da più thread differenti.

Inoltre, questo post è stato molto utile per capire la relazione tra ObserveOn e SubscribeOn .

Mi ha aiutato a capire questo pensando a SubscribeOn come l’impostazione del thread che ha “passato” la catena e ObserveOn come l’impostazione del thread “trasmesso” alla catena.

Thread di sottoscrittori

Il codice seguente utilizza thread denominati con cui puoi giocare.

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

L’output di quanto sopra è:

Subscribing on Thread1 Observing 1 on Thread2

È anche interessante vedere che quando si commenta la riga SubscribeOn , l’output è:

Subscribing on Main Observing 1 on Thread2

Perché per impostazione predefinita l’abbonamento “passa” a seconda del thread in esecuzione ( Main qui). Quindi l’ ObserveOn “passa giù” Thread2 .

Se invece commenta la linea ObserveOn , l’output è:

Subscribing on Thread1 Observing 1 on Thread1

Perché “passiamo” la sottoscrizione su Thread1 e, per impostazione predefinita, questo stesso thread è “passato” e utilizzato per eseguire l’osservazione.

In un contesto GUI, per mantenere le cose reattive si desidera la minima quantità di lavoro svolto sul thread della GUI, ma è necessario l’abbonamento fatto sul thread della GUI (per sincronizzare gli aggiornamenti dell’interfaccia utente). Quindi vuoi .Observare sul thread della GUI.

Le differenze sono fondamentalmente che subscribeOn forza l’intera pipeline ad essere processata da un altro thread, ma con observerOn solo i passaggi nella pipeline definiscono dopo che observerOn verrà eseguito in un altro thread solo dopo averlo impostato verrà eseguito in un altro thread.

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

Tutti i passaggi della pipeline verranno eseguiti in un altro thread.

  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()