TPL Dataflow and async/await vs CCR - part 4

Today I wanted to show a number of simple examples of how to do things with TPL data-flow compared to CCR. Creating a CCR port and posting and then receiving on it asynchronously is one fundamental scenario in CCR. This is what it looks like with TPL data-flow:

  1: var port = new BufferBlock<int>();
 2: port.Post(42);
 3: int result = await port.ReceiveAsync();

If you want to explicitly extract data from a port this is how you would do it:

  4: int item;
 5: if (port.TryReceive(out item))
 6: {
 7:     ProcessItem(item);
 8: }

Very similar to CCR which would just use the Port.Test method on line X. Remember how we in the test coded needed a synchronous way to receive data on a port using ManualResetEvents. Much easier with TPL data-flow:

  9: int item = port.Receive();

One larger difference is that in CCR concurrent processing of handlers on ports is the default while in TPL data-flow the default is to process one item at the time. This is how you can change that:

  10: var port = new ActionBlock<int>(
 11:     item => ProcessItem(item), 
 12:     new DataflowBlockOptions 
 13:         { MaxDegreeOfParallelism = Environment.ProcessorCount });

It is also very easy to introduce interleaving as in CCR. That is limit the processing across multiple ports. It can look something like this:

  14: var options = new DataflowBlockOptions() { 
 15:     TaskScheduler = 
 16:         new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler
 17: };
 18: var p1 = new ActionBlock<int>(item => ProcessItem(item), options);
 19: var p2 = new ActionBlock<int>(item => ProcessItemDifferent(item), options);

These are just a few differences that should get you started. Bottom line is that if you're used to CCR it is very easy to switch over to use TPL data-flow if you ask me.