Domanda

Quando uno sceglie di utilizzare Rx oltre TPL o il 2 di quadri ortogonali?

Da quello che ho capito Rx è principalmente destinato a fornire un'astrazione su eventi e consentire la composizione, ma permette di fornire un'astrazione sulle operazioni asincrone.utilizzando il Createxx i sovraccarichi e i Fromxxx sovraccarichi e disdetta via smaltimento IDisposable restituiti.

TPL, inoltre, fornisce un'astrazione per operazioni con Attività e cancellazione abilità.

Il mio dilemma è quando utilizzare e per quali scenari?

È stato utile?

Soluzione

Lo scopo principale di Rx non è quello di fornire un'astrazione sugli eventi. Questo è solo uno dei suoi esiti. Il suo scopo principale è quello di fornire un modello push componibile per le collezioni.

Il quadro reattiva (Rx) si basa sulla IObservable<T> essere il doppio di matematica IEnumerable<T>. Quindi, piuttosto che "pull" elementi da una collezione utilizzando IEnumerable<T> possiamo avere oggetti "spinto" a noi tramite IObservable<T>.

Naturalmente, quando abbiamo effettivamente andare alla ricerca di fonti osservabili cose come gli eventi e le operazioni asincrone sono ottimi candidati.

Il quadro reattivo richiede naturalmente un modello multi-threaded per essere in grado di guardare le fonti dei dati osservabili e di gestire le query e abbonamenti. Rx rende di fatto un uso pesante del TPL per fare questo.

Quindi, se si utilizza Rx si sta implicitamente utilizza il TPL.

Si potrebbe utilizzare il TPL direttamente, se lo si desidera il controllo diretto sulle vostre attività.

Ma se si dispone di fonti di dati che si desidera osservare ed eseguire le query allora consiglio vivamente il quadro reattivo.

Altri suggerimenti

Alcune linee guida mi piace seguire:

  • Sono si tratta di dati che non hanno origine. I dati che arriva quando vuole? Poi RX.
  • Am I, originari calcoli e la necessità di gestire la concorrenza? Poi TPL.
  • Perchè sono gestendo più risultati, e la necessità di scegliere tra loro in base al tempo? Poi RX.

Mi piace punti elenco di Scott W. Per mettere alcuni esempi più concreti in Rx mappe davvero ben al

  • flussi consumano
  • l'esecuzione non-blocking lavoro asincrone come le richieste web.
  • eventi in streaming (sia eventi .net come il movimento del mouse o di autobus eventi di tipo messaggio)
  • Composizione "flussi" di eventi insieme
  • operazioni di stile Linq
  • L'esposizione flussi di dati dal vostro API pubblica

TPL sembra mappare bene per

  • parallelizzazione interna del lavoro
  • eseguendo-bloccanti non lavoro asincrone come le richieste web
  • performing flussi di lavoro e continuazioni

Una cosa che ho notato con IObservable (Rx) è che diventa pervasiva. Una volta nella vostra base di codice, in quanto sarà senza dubbio essere esposto tramite altre interfacce, alla fine comparirà su tutto l'applicazione. Immagino che questo può essere spaventoso in un primo momento, ma la maggior parte della squadra è abbastanza comodo con Rx ora e amo la quantità di lavoro che ci salva.

IMHO Rx sarà la biblioteca dominante sul TPL come già è supportato in .NET 3.5, 4.0, Silverlight 3, Silverlight 4 e Javascript. Questo significa che dovete in modo efficace per imparare uno stile ed è applicabile a molte piattaforme.

Modifica : Ho cambiato idea su Rx essere dominante su TPL. Risolvono problemi diversi, quindi non dovrebbe davvero essere confrontati così. Con .NET 4.5 / C # 5.0 Async / attendono parole chiave ulteriormente noi legare al TPL (che è buono). Per una profonda discuson sulla Rx vs eventi vs TPL ecc controllare le primo capitolo del mio IntroToRx.com

Aggiornamento Dicembre 2016: Se si hanno a disposizione 30 minuti, vi consiglio di leggere Joe Duffy di prima mano invece che la mia speculazione.Credo che la mia analisi tiene bene, ma se hai trovato questa domanda vi consiglio vivamente di vedere il post sul blog invece di queste risposte, perché oltre al TPL vs Rx.NET egli copre anche MS progetti di ricerca (Midori, Cosmo).

http://joeduffyblog.com/2016/11/30/15-years-of-concurrency/


Penso che MS ha fatto un grande errore, oltre a correzione dopo .NET 2.0 è venuto fuori.Hanno introdotto diversi per la gestione della concorrenza Api, tutti allo stesso tempo da diverse parti della società.

  • Steven Toub stava spingendo duro per thread-safe primitive per sostituire Evento (che ha iniziato come Future<T> e trasformato in Task<T>)
  • MS Ricerca aveva MIN-LINQ e Reattiva Estensioni (Rx)
  • Hardware/Embedded aveva robotica cuntime (CCR)

Nel frattempo, molti managed API squadre cercavano di vivere con APM e Threadpool.QueueUserWorkItem(), non sapendo se Toub avrebbe vinto la sua lotta per la nave Future<T>/Task<T> in mscorlib.dll.Alla fine sembra che di copertura, e spediti entrambi Task<T> e IObservable<T> in mscorlib, ma non permettere a qualsiasi altra Rx Api (non ancora ISubject<T>) in mscorlib.Penso che questa siepe finito per provocare un enorme quantità di duplicazione (più tardi) e fatica sprecata dentro e fuori l'azienda.

Per la duplicazione di vedere: Task vs IObservable<Unit>, Task<T> vs AsyncSubject<T>, Task.Run() vs Observable.Start().E questa è solo la punta dell'iceberg.Ma ad un livello superiore di prendere in considerazione:

  • StreamInsight - SQL flussi di eventi, in codice nativo ottimizzato, ma evento query definite utilizzando la sintassi LINQ
  • TPL Dataflow - costruito sul TPL, costruito in parallelo alla Rx, ottimizzato per la messa a punto di filettatura parallelismo, non è bravo a comporre le query
  • Rx - Incredibile espressività, ma pieno di pericoli.Mescola 'hot' con i flussi IEnumerablestile metodi di estensione, il che significa che è molto facile bloccare per sempre (chiamata First() in un caldo flusso non restituisce mai).Pianificazione dei limiti di limitare il parallelismo) è fatto via piuttosto strano SubscribeOn() i metodi di estensione, che sono stranamente implicita e difficile da ottenere.Se si inizia a imparare Rx riserva un lungo tempo per imparare tutte le insidie da evitare.Ma Rx è davvero l'unica opzione se la composizione di complessi flussi di eventi o avete bisogno di un filtraggio complesso/query.

Non credo Rx ha una possibilità di combattere in adozione su vasta scala fino a quando MS navi ISubject<T> in mscorlib.Che è triste, perché Rx contiene alcuni molto utile in cemento armato (generico), come TimeInterval<T> e Timestamped<T>, e credo che dovrebbero essere in Core/mscorlib come Nullable<T>.Inoltre, System.Reactive.EventPattern<TEventArgs>.

Direi che il TPL flusso di dati coperture specialized sottoinsieme di funzionalità in Rx.Flusso dei dati è per il trattamento dei dati, che può assumere quantità misurabili di tempo, considerando che la Rx è per gli eventi, come la posizione del mouse, stati di errore, ecc, dove la manipolazione del tempo è trascurabile.

Esempio:il "subscribe" gestore è asincrona e non si desidera più di 1 esecutore al momento.Con Rx è bloccato, non c'è altro modo intorno ad esso, perché Rx è async-agnostico e non minaccia asincrono in modo speciale in molti luoghi.

.Subscribe(myAsyncHandler().Result)

Se non bloccare, quindi Rx considera che l'azione è stata completata mentre il conduttore viene ancora eseguita in modo asincrono.

Si potrebbe pensare che se si fa

.ObserveOn(Scheduler.EventLoopSchedule)

che problema è risolto.Ma questo si romperà la vostra .Completo (a) flusso di lavoro, perché Rx viene da pensare che si è fatto appena esecuzione del programma e si chiude l'applicazione senza aspettare async il completamento dell'operazione.

Se si desidera lasciare non più di 4 concorrenti async attività di Rx non offre nulla di fuori della scatola.Forse si può modificare qualcosa implementando proprio scheduler, buffer, ecc.

TPL flusso di dati offrono molto bella soluzione in ActionBlock.È possibile limitare l'azione simultanea di certo numero e comprende operazioni asincrone, quindi chiamata a Completare() in attesa del Completamento consente di fare esattamente ciò che ti aspetti:in attesa che tutti i in corso async attività da completare.

Un'altra caratteristica TPL è "contropressione".Diciamo che hai scoperto un errore nella vostra routine di gestione e la necessità di ricalcolo ultimo mese.Se ti iscrivi la tua fonte, utilizzando Rx, e pipeline, contiene una sovrabbondanza di buffer, o ObserveOn, che è a corto di memoria in questione di secondi, in quanto fonte di continuo a leggere più velocemente di elaborazione in grado di gestire.Anche se si sceglie di implementare il blocco dei consumatori, la vostra fonte, possono soffrire di blocco chiamate, ad esempio, se la sorgente è asincrona.Nel TPL è possibile implementare fonte

while(...)
    await actionBlock.SendAsync(msg)

che non blocca fonte di sicurezza saranno in attesa mentre il conduttore è sovraccarico.

In generale, ho trovato che la Rx è una buona misura per le azioni che sono il tempo e computazionalmente leggero.Se il tempo di elaborazione diventa sostanziale, nel mondo di strani effetti collaterali ed esoterico di debug.

La buona notizia è che il TPL flusso di dati isolati gioco molto bello con Rx.Hanno AsObserver/AsObservable adattatori e si può attaccare loro, al centro del Rx pipeline quando necessario.Ma Rx è molto più modelli e casi d'uso.Così la mia regola è quella di iniziare con Rx e aggiungere TPL flusso dei dati necessari.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top