Pregunta

Cuando uno elige habría de utilizar más de Rx o TPL son los 2 marcos ortogonales?

Por lo que entiendo Rx está destinado principalmente para proporcionar una abstracción sobre los acontecimientos y permitir que la composición sino que también permite para proporcionar una abstracción de las operaciones asíncronas. usando las sobrecargas Createxx y las sobrecargas de XXX y cancelación a través de la disposición de la IDisposable regresó.

TPL también proporciona una abstracción para las operaciones a través de las habilidades de tareas y cancelación.

Mi dilema es cuándo usar el cual y para qué escenarios?

¿Fue útil?

Solución

El objetivo principal de Rx no es proporcionar una abstracción sobre los acontecimientos. Este es sólo uno de sus resultados. Su objetivo principal es proporcionar un modelo de inserción componibles para las colecciones.

El marco reactivo (Rx) se basa en IObservable<T> ser el doble matemática de IEnumerable<T>. Así que en lugar de artículos de "atracción" de una colección utilizando IEnumerable<T> podemos tener objetos "empujados" a nosotros a través de IObservable<T>.

Por supuesto, cuando en realidad nos vamos en busca de fuentes observables cosas como eventos y operaciones asíncronas son excelentes candidatos.

El marco reactiva requiere naturalmente un modelo multi-hilo para poder ver las fuentes de datos observables y para gestionar las consultas y suscripciones. Rx en realidad hace un uso intensivo de la TPL para hacer esto.

Así que si usa Rx está implícita utilizando el TPL.

Se podría utilizar el TPL directamente si así lo desea el control directo sobre sus tareas.

Sin embargo, si tiene fuentes de datos que desea observar y realizar consultas en entonces yo recomendaría el marco reactiva.

Otros consejos

Entre las pautas que me gustan a seguir:

  • Am I se trata de datos que no sean originarios. Los datos que llega cuando le plazca? Entonces RX.
  • cálculos originarios Am I y necesidad de gestionar la concurrencia? Entonces TPL.
  • ¿Soy la gestión de múltiples resultados, y necesita elegir una de ellas basada en el tiempo? Entonces RX.

I como viñetas de Scott W. Para poner algunos ejemplos más concretos en Rx mapas muy bien a

  • consumen corrientes
  • realizar sin bloqueo de trabajo asíncrono como las peticiones web.
  • streaming de eventos (eventos ya sea .NET como el movimiento del ratón OR eventos de tipo de mensaje de servicio de autobuses)
  • Componer "corrientes" en los eventos juntos
  • operaciones de estilo Linq
  • La exposición de los flujos de datos de su API pública

TPL parece muy bien asignar a

  • paralelización interna del trabajo
  • realizar sin bloqueo asíncrono obra como las peticiones web
  • flujos de trabajo de realizar y continuaciones

Una cosa que he notado con IObservable (Rx) es que se vuelve omnipresente. Una vez en su base de código, ya que sin duda va a estar expuesto a través de otras interfaces, con el tiempo aparecerá en todo su aplicación. Me imagino que esto puede dar miedo al principio, pero la mayoría del equipo es bastante cómodo con Rx y me encanta la cantidad de trabajo que nos salva.

En mi humilde opinión Rx será la biblioteca dominante sobre el TPL como ya es compatible con .NET 3.5, 4.0, Silverlight 3, 4 Silverlight y Javascript. Esto significa que efectivamente tienen que aprender un estilo y es aplicable a muchas plataformas.

Editar : He cambiado de opinión acerca de Rx ser dominante sobre TPL. Que resuelven diferentes problemas por lo que en realidad no debería ser comparados por el estilo. Con .NET 4.5 / C # 5.0 del asíncrono / Await palabras clave nos ata más a la TPL (que es bueno). Para una profunda discuson en Rx vs vs eventos TPL etc. echa un vistazo a la primer capítulo de mi libro en línea IntroToRx.com

Actualización, Diciembre 2016: Si usted tiene 30 minutos, le recomiendo que lea relato de primera mano de Joe Duffy en lugar de mi especulación. Creo que mi análisis se sostiene bien, pero si usted ha encontrado esta pregunta le recomiendo que vea la entrada de blog en lugar de estas respuestas porque además de TPL vs Rx.NET también cubre MS proyectos de investigación (Midori, Cosmos).

http://joeduffyblog.com/2016/ 11/30/15-años-de-la concurrencia /


Creo MS cometió un gran error sobre-corregir después de .NET 2.0 salió. Se presentaron muchas API diferente de gestión de concurrencia, todo al mismo tiempo desde diferentes partes de la empresa.

  • Steven Toub estaba empujando duro para las primitivas compatibles con el proceso para reemplazar eventos (que comenzó como Future<T> y se convirtió en Task<T>)
  • Investigación MS tenía MIN-LINQ y extensiones reactivas (Rx)
  • Hardware / Embedded Had robótica cuntime (CCR)

Mientras tanto muchos equipos de API administradas estaban tratando de vivir con APM y Threadpool.QueueUserWorkItem(), sin saber si Toub ganaría su lucha para enviar Future<T> / Task<T> en mscorlib.dll. Al final parece que pretende cubrir y enviados tanto Task<T> y IObservable<T> en mscorlib, pero no permitieron que cualquier otra Rx API (ni siquiera ISubject<T>) en mscorlib. Creo que esta cobertura terminó causando una enorme cantidad de duplicación (más tarde) y la pérdida de esfuerzo y en el interior fuera de la empresa.

Para la duplicación, véase: Task vs IObservable<Unit>, Task<T> vs AsyncSubject<T>, Task.Run() vs Observable.Start(). Y esto es solo la punta del iceberg. Pero a un nivel más alto en cuenta:

  • StreamInsight - SQL flujos de eventos, optimizado de código nativo, pero consultas de eventos definidos usando la sintaxis de LINQ
  • TPL flujo de datos - construido sobre TPL, construido en paralelo a Rx, optimizado para ajustar el paralelismo roscado, no es bueno en las consultas que componen
  • Rx - expresividad increíble, pero lleno de peligros. 'calientes' corrientes se mezcla con los métodos de extensión de estilo IEnumerable, lo que significa que bloquea muy fácilmente para siempre (llamando First() en una corriente caliente, nunca vuelve). límites de programación (que limita el paralelismo) se realiza a través de los métodos de extensión SubscribeOn() bastante extraño, que son extrañamente implícita y difícil de conseguir derecha. Si se comienza a aprender reserva Rx mucho tiempo para aprender todas las trampas que se deben evitar. Pero Rx es realmente la única opción si la composición de flujos de eventos complejos o si necesita compleja filtrado / consulta.

No creo Rx tiene una oportunidad de luchar por la adopción amplia hasta MS barcos ISubject<T> en mscorlib. Lo cual es triste, porque Rx contiene algunos tipos concretos de gran utilidad (genéricos), como TimeInterval<T> y Timestamped<T>, que creo que debería estar en Core / mscorlib como Nullable<T>. Además, System.Reactive.EventPattern<TEventArgs>.

Yo diría que las cubiertas TPL de flujo de datos especializados subconjunto de la funcionalidad de Rx. Dataflow es para el procesamiento de datos que puede tomar cantidad mensurable de tiempo, mientras que Rx es para eventos, tales como la posición del ratón, estados de error, etc, donde el tiempo de manipulación es insignificante.

Ejemplo: el "subscribe" manejador es asíncrono y que no quieren más de 1 ejecutor en el momento. Con Rx tiene que bloquear, no hay otra manera alrededor de ella, porque es asíncrono Rx-agnóstica y no lo hace asíncrono amenaza de una manera especial en muchos lugares.

.Subscribe(myAsyncHandler().Result)

Si no bloquear, entonces Rx considerará que la acción se ha completado, mientras manejador todavía se está ejecutando de forma asíncrona.

Se podría pensar que si lo hace

.ObserveOn(Scheduler.EventLoopSchedule)

de problema está resuelto. Pero esto va a romper el flujo de trabajo integro (), porque Rx va a pensar que se realiza tan pronto como cronograma de ejecución y que se renuncie a su aplicación sin esperar a finalizar la operación asíncrona.

Si desea permitir no más de 4 tareas asíncronas simultáneas de Rx no ofrece nada fuera de la caja. Tal vez se puede piratear algo mediante la implementación de su propio programador, tampón, etc.

TPL flujo de datos ofrecen una solución muy agradable en ActionBlock. Se puede estrangular acciones simultáneas a cierto número y lo hace entender asíncrono operaciones, así que llamar completa () ya la espera de Completado hará exactamente lo que cabría esperar:. Espera de todos en curso asíncrono tareas para completar

Otra característica es TPL tiene "contrapresión". Digamos que usted descubrió un error en su rutina de manejo y la necesidad de recálculo de datos último mes. Si se suscribe a su origen mediante Rx, y su tubería contiene barreras no acotados, o ObserveOn, de lo que se quedará sin memoria en cuestión de segundos porque la fuente se mantendrá la lectura de procesamiento más rápido que puede manejar. Incluso si se implementa el bloqueo de los consumidores, su fuente puede sufrir de llamadas de bloqueo, por ejemplo, si la fuente es asíncrona. En TPL se puede implementar como fuente

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

que no bloquea fuente todavía esperará mientras controlador está sobrecargado.

En general, he encontrado que Rx es buena opción para las acciones que son computacionalmente tiempo y la luz. Si el tiempo de procesamiento se vuelve importante, usted está en el mundo de los efectos secundarios extraños y depuración esotérico.

Buena noticia es que la TPL de flujo de datos bloques juegan muy bien, con Rx. Tienen AsObserver / adaptadores AsObservable y se puede pegarlas en el medio de la tubería Rx cuando sea necesario. Pero Rx tiene mucho más patrones y casos de uso. Así que mi regla de oro es comenzar con Rx y añadir TPL flujo de datos según sea necesario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top