14

I just want to learn both and how to use them together. I understand that they can complement each other I just could not find an example of someone actually doing it.

naeron84
  • 2,955
  • 3
  • 30
  • 37
  • 2
    SO is best for specific questions how to do something. “Give me an example of X” doesn't fit that very well. – svick Jul 08 '12 at 15:04
  • Ok, you are right about the form of the question but i think the issue is still valid. Maybe "How to use them in combination to effectively exploit the features from both?" is more appropriate. – naeron84 Jul 08 '12 at 17:24
  • @naeron84 Would it be sufficient to look at a combined C#-async + Rx example? – GregC Jul 10 '12 at 15:29
  • @GregC Actually I want to use f# but async is not related to TPL Dataflow blocks at least not explicitly. – naeron84 Jul 10 '12 at 19:00
  • @naeron84 Would it then be OK for me to add an F# tag onto your question? – GregC Jul 10 '12 at 19:11
  • @naeron84 I can see how quite a few SO users would vote to have this question closed. Is there a specific problem that you need to solve that involves both technologies? – GregC Jul 10 '12 at 19:12
  • @GregC It's not an f# specific problem. And no, there is not any specific problem I just want to combine them if possible so I can enjoy the features from both. – naeron84 Jul 10 '12 at 19:39
  • What exactly do you expect from that example, apart from showing you that the methods [`AsObservable()`](http://msdn.microsoft.com/en-us/library/hh160306%28v=vs.110%29) and [`AsObserver()`](http://msdn.microsoft.com/en-us/library/hh160359%28v=vs.110%29) exist? – svick Jul 10 '12 at 20:57
  • 1
    @svick The problems involving parallelism and asynchronity. What happens if i mix them together and stuff like that. I'm staring to think that the question is to trivial or to hard or pointless and I'm not getting something very basic :) – naeron84 Jul 10 '12 at 21:48
  • I believe there is nothing special about combining the two in that regard. Just write your TDF code like you would if you were using TDF alone and write your Rx code like you would if you were using Rx alone. – svick Jul 10 '12 at 21:54
  • This seems a very open question. Which version of .NET 3.5, 4, 4.5? Which version of Rx? What are you hoping to do? Continuations, streaming? Are you looking to leaverage Futures or Single value sequences, the TaskPool vs Schedulers...? The only valid answer would be pages long. Please be more specific. – Lee Campbell Jul 26 '12 at 09:37

1 Answers1

21

Let me start with a bit of background.

The .NET framework has a number of special types - either proper classes or interfaces - Task<T>, IObservable<T>, Nullable<T>, IEnumerable<T>, Lazy<T>, etc - that provide special powers to the underlying type T.

The TPL uses Task<T> to represent asynchronous computation of a single value of T.

Rx uses IObservable<T> to represent asynchronous computation of zero or more values of T.

It's the "asynchronous computation" aspect of both of these that bring TPL and Rx together.

Now, the TPL also uses the type Task to represent the asynchronous execution of an Action lambda, but this can be considered a special case of Task<T> where T is void. Very much like a standard method in c# returns void like so:

public void MyMethod() { }

Rx also allow for the same special case with use of a special type called Unit.

The difference between the TPL and Rx is in the number of values returned. TPL is one and only one whereas Rx is zero or more.

So, if you treat Rx in a special way by only working with observable sequences that return a single value you can do some computations in a similar way to the TPL.

For example, in the TPL I could write:

Task.Factory
    .StartNew(() => "Hello")
    .ContinueWith(t => Console.WriteLine(t.Result));

And in Rx the equivalent would be:

Observable
    .Start(() => "Hello")
    .Subscribe(x => Console.WriteLine(x));

I could go one step further in Rx by specifying that the TPL should be used to execute the computation like so:

Observable
    .Start(() => "Hello", Scheduler.TaskPool)
    .Subscribe(x => Console.WriteLine(x));

(By default the Thread Pool is used.)

Now I could do some "mixing and matching". If I add a reference to the System.Reactive.Threading.Tasks namespace I can move between tasks and observables quite easily.

Task.Factory
    .StartNew(() => "Hello")
    .ToObservable()
    .Subscribe(x => Console.WriteLine(x));

Observable
    .Start(() => "Hello")
    .ToTask()
    .ContinueWith(t => Console.WriteLine(t.Result));

Notice the ToObservable() & .ToTask() calls and the resulting flips from one library to the other.

If I have an observable that returns more than one value I can use the observable .ToArray() extension method to turn multiple sequence values into a single array value that can be turned into a task. Like so:

Observable
    .Interval(TimeSpan.FromSeconds(1.0))
    .Take(5) // is IObservable<long>
    .ToArray()
    .ToTask() // is Task<long[]>
    .ContinueWith(t => Console.WriteLine(t.Result.Length));

I think this is a fairly basic answer to your question. Is it what you were expecting?

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 21
    TPL Dataflow is a very different library from TPL, so I don't feel the answer does not precisely address the question. The discussion was, however, noteworthy, so +1. – GregC Jul 10 '12 at 15:17
  • Too bad the .Net type system doesn't actually allow `Task`. – svick Jul 10 '12 at 15:45
  • 2
    Sorry but as GregC stated before i need an example involving TPL Dataflow not "just" TPL. What I want is to combine TPL Dataflow blocks and with Rx. – naeron84 Jul 10 '12 at 18:59
  • My apologies - I did not know about `DataFlow`. Sorry I haven't answered your question. – Enigmativity Jul 11 '12 at 01:18
  • 1
    @svick - The lack of `Task` is what `IObservable` is meant to represent. Could you not use `Task` for the same thing as `Task`? – Enigmativity Jul 11 '12 at 01:19
  • @Enigmativity Mostly, yeah, except it's not as nice. For example, you still have to explicitly `return Unit.Default;` at the end of each `Unit`-returning function. – svick Jul 11 '12 at 07:19