C# Corner

Exploring .NET 4.5 Parallel Dataflow - Part 2

In Part 2 of this three-part series on dataflow programming with the Task Parallel Library, Eric Vogel shows you how to create a Windows 8 application that uses a composite parallel data flow.

In Part 1 of this series on building Windows 8 applications with the Task Parallel Library (TPL) dataflow components in the .NET Framework, I covered how to use the ActionBlock and the TransformBlock dataflow blocks. This time, I'll take it a step further and show you how to link dataflow blocks, to create more complex parallel data flows. A common usage pattern is the producer/consumer scenario. By linking dataflow blocks together, one block can post a message that is then pumped through one or many dataflow blocks that further process the data.

To demonstrate this concept, let's look at a hypothetical data flow for an application. Say you're reading temperatures from a sensor in regular sub-second intervals. The data needs to be displayed as it's read in real-time. In addition, you need to be able to apply some post processing to the raw temperatures such as formatting for Fahrenheit, and comparisons to the average temperature for the current date.

This scenario tackles a few common dataflow issues. For one, the data needs to be broadcast to multiple sources. Secondly, the data must be read by multiple sources in order to be further processed and formatted. Luckily, the Task Parallel Dataflow (TDF) library includes the BroadcastBlock, which makes implementing this scenario straightforward. Without further ado, let's get down to the details.

Open up Visual Studio 2012 Release Candidate and create a C# Metro style App. First, open up MainPage.xaml and use the XAML from the root Grid element in Listing 1. The UI is fairly simple. Three sets of stack panels are associated with the three buttons on the page.

Broadcasting Data
For this sample application, you'll need to have the Parallel Dataflow NuGet package installed. Refer to Part 1 for installation instructions. Now that the TDF package is installed, open up MainPage.xaml.cs and add the following using statements:

 using System.Threading.Tasks;
 using System.Threading.Tasks.Dataflow;

Then add the BroadcastBlock to the MainPage class:

 BroadcastBlock<int> _broadcaster;

The BroadcastBlock will be responsible for transferring temperature data to the various TransformBlock objects for further processing. Once a Transform block has processed and formatted a piece of datum, it'll pump the datum to an ActionBlock for UI display.

Next, instantiate the _broadcaster block in the OnNavigatedTo event of the page:

 protected override void OnNavigatedTo(NavigationEventArgs e)
{
    _broadcaster = new BroadcastBlock<int>(x => x);
}

Now setup the click event handler for the BroadCast button. Within the event, an ActionBlock is created that will display a message via the Message TextBlock on the page:

private async void BroadCast_Click(object sender, RoutedEventArgs e)
{
    ActionBlock<int> simpleDisplayer =
CreateUiUpdateActionBlock<int>(Message);
    _broadcaster.LinkTo(simpleDisplayer);
    await BroadCastData();
}

The CreateUiUpdateActionBlock<T> method is a simple helper function that creates an ActionBlock to set the Text property of a TextBlock element on the UI thread:

private ActionBlock<T> CreateUiUpdateActionBlock<T>(TextBlock element)
{
    return new ActionBlock<T>(x =>
        element.Text = x.ToString(),
          new ExecutionDataflowBlockOptions() { TaskScheduler =
TaskScheduler.FromCurrentSynchronizationContext() });
}

Next, the simpleDisplayer ActionBlock is linked to the _broadcaster block through the LinkTo method:

 _broadcaster.LinkTo(simpleDisplayer);

Now, there's a lot of power in that link statement. Whenever any data is posted to the _broadcaster block, it will immediately be propagated to the simpleDisplayer block asynchronously.

Next, I'll generate and post some randomized temperature data to the _broadcaster block by awaiting the BroadCastData method:

await BroadCastData();
private async Task BroadCastData()
{
    Random r = new Random((int)System.DateTime.Now.Ticks);
    int temp = 0;

    for (int i = 0; i < 1000; i++)
    {
        await Task.Delay(125);
        temp = r.Next(60, 80);
        await _broadcaster.SendAsync(temp);
    }
}

I've added a 125-msec delay between temperature datum postings to more accurately simulate reading from a sensor.

Post Processing Data
Now that the application is correctly broadcasting and displaying temperature data, let's get started on the second requirement. When the Transform button is clicked, the temperature should be displayed in the Fahrenheit format. To accomplish this task, the TransformBlock is ideal because it can receive a raw integer temperature and format it to a Fahrenheit formatted string:

 TransformBlock<int, string> _formatter = new TransformBlock<int, string>(x =>
 String.Format("{0:G2}°F", x));

Once the data has been cleaned up, it can be displayed to the user via an ActionBlock:

ActionBlock<string> transformedDisplayed =         
CreateUiUpdateActionBlock<string>(TransformedMessage);

The last step is to link all of the dataflow blocks together so that the _broadcaster sends data to the formatter, which displays data via the transformDisplayed block:

 _broadcaster.LinkTo(formatter);
 formatter.LinkTo(transformedDisplayed);

private void Transform_Click(object sender, RoutedEventArgs e)
{
    TransformBlock<int, string> formatter = new TransformBlock<int, string>(x =>
    String.Format("{0:G2}°F", x));
    ActionBlock<string> transformedDisplayed =
CreateUiUpdateActionBlock<string>(TransformedMessage);
    _broadcaster.LinkTo(formatter);
    formatter.LinkTo(transformedDisplayed);
}

Now, let's implement the last requirement for displaying a formatted Fahrenheit delta temperature between a read temperature and the average temperature for the day.

The processing will occur in the PostProcess button click event handler as shown in Listing 2 .

Computing the delta average temperature is easily accomplished via a TransformBlock:

 const int average = 75;
 TransformBlock<int, int> averageDelta = new TransformBlock<int, int>(x => x - average);

Now another TransformBlock is created to format the delta temperature to be displayed in degrees Fahrenheit. In addition, a '+' or '-' is pretended to the temperature to indicate the change:

TransformBlock<int, string> formatPost = new TransformBlock<int, string>(x => {
  string preFix = string.Empty;
  if (x > 0) preFix = "+";
  return String.Format("{0}{1:G2}°F", preFix, x);
 });

Finally, an ActionBlock is created to update the text of the PostProcessMessage TextBlock on the page, and the data flow blocks are linked together:

ActionBlock<string> postProcessDisplayer =
CreateUiUpdateActionBlock<string>(PostProcessMessage);
_broadcaster.LinkTo(averageDelta);
averageDelta.LinkTo(formatPost);
formatPost.LinkTo(postProcessDisplayer);

You should now be able to run the completed application shown in Figure 1.

Figure 1. Completed sample application

As you can see, the Task Parallel Dataflow library is very versatile for implementing complex parallel data flows. Through dataflow block composition, a myriad of problems can be solved in a simple, efficient and elegant manner. Stay tuned for Part 3 in this series on dataflow programming with the Task Parallel Library dataflow components in .NET Framework 4.5 to learn how to create custom dataflow blocks.

About the Author

Eric Vogel is a Sr. Software Developer at Kunz, Leigh, & Associates in Okemos, MI. He is the president of the Greater Lansing User Group for .NET. Eric enjoys learning about software architecture and craftsmanship, and is always looking for ways to create more robust and testable applications. Contact him at vogelvision@gmail.com.

comments powered by Disqus

Reader Comments:

Fri, Feb 1, 2013 Jaydee buy accutane online nwagq buy cialis online 74560 order viagra online eueuoo

http://www.acnegoodbye.net/ DOT nwagq http://www.buyedmedsonline.com/ DOT 74560 http://www.edpillsguide.com/ DOT eueuoo

Wed, Jan 30, 2013 Carley auto owners insurance 092929 cheap auto insurance itvl viagra for woman :-P

http://cheapautoinsurer.net/ DOT 092929 http://www.onlinecheapautoinsurance.net/ DOT itvl http://edmedsinfo.com/ DOT :-P

Wed, Jan 16, 2013 Jalen cheap auto insurance twaah cheap auto insurance =-( car insurance quotes bbfhif

http://www.autoinsurers4u.com/ DOT twaah http://www.onlinecheapautoinsurance.net/ DOT =-( http://www.bestautoinsurancepolicies.net/ DOT bbfhif

Wed, Jan 16, 2013 Moon florida auto insurance 273112 car insurance quotes :[[[ life insurance quotes 47218

http://cheapautoinsurer.net/ DOT 273112 http://www.quotesfromtopinsurers.com/ DOT :[[[ http://www.lifeinsuranceshopping.net/ DOT 47218

Wed, Oct 3, 2012 sarabjeet INDIA

Thanks for all the information,it was very helpful and i really like that you are providing information on .net training ,being enrolled in .net freshers training with projects live training http://www.wiziq.com/course/57-fresher-training-projects i was looking for such .net fresher training to assist me and your information helped me a lot.Really like that you are providing such information . Thanks.

Add Your Comments Now:

Your Name:(optional)
Your Email:(optional)
Your Location:(optional)
Comment:
Please type the letters/numbers you see above

.NET Insight

Sign up for our newsletter.

I agree to this site's Privacy Policy.