Working with .NET Framework Task Parallel Library and Windows Presentation Foundation

Windows Presentation Foundation (WPF) embraced the power of DirectX and made the GPU a first-class citizen on .NET. Task Parallel Library (TPL) has made .NET Parallel Programming more accessible. Separately WPF and TPL comprise great leaps in developer productivity and application quality. Combine the two technologies and a .NET developer mixes the full capabilities of a modern GPU with the responsiveness that can only be achieved with asynchronous code.

Like all .NET technologies there are many approaches to combining the classes within the .NET Framework. Using some code samples I'm going to demonstrate how to incorporate TPL into WPF.

Sample Overview

The sample code simulates doing work with the Thread.Sleep method and then updates a TextBox with the current time and date. Had the goal been to write a synchronous solution, rather than asynchronous solution, the code would have looked like the example below.

Thread.Sleep(4000);
_txtUpdate.Text = "Updated on " + DateTime.Now.ToString();

Of course, most users don't like an unresponsive User Interface. I'm not aware of many users who would tolerate a 4 second wait each time they pressed a button. Therefore most developers opt for an asynchronous version of the code above. The asynchronous version of the code above that utilizes TPL appears below.

//Work to perform
Task<string> doWork = new Task<string>(() =>
	{
		Thread.Sleep(4000);
		return "Updated on " + DateTime.Now.ToString();
	}
);

//Update the Text value
Action<Task<string>> toUpdate = t =>
{
	try{ _txtUpdate.Text = t.Result;}
	catch (Exception ex)
	{
	Debugger.Break();
	}
};

//Link the two
doWork.ContinueWith(toUpdate, TaskScheduler.FromCurrentSynchronizationContext());
//Schedule the work and return from the push button event
doWork.Start();

At first glance it may appear that the code complexity grew a magnitude or two. In reality most of the additional code was added so the two lines appearing in the synchronous example could be executed by TPL. To execute code in TPL a developer must divide the work into Tasks.

Tasks

A complete review of the Task class is beyond the scope of this article. You'll find more information in this article on 'Understanding Tasks in .NET Framework 4.0 Task Parallel Library'. Though there is more to a Task class; Tasks can be considered a wrapper for a Delegate. I like to think of Tasks as TPL units of work.

The sample utilizes two Tasks. The first Task executes the simulated work and the second Task updates the User Interface. Later in the article I'll address why two Tasks were required.

TPL executes a Task on a ThreadPool managed by a TaskScheduler class. TaskSheduler decides where and when to execute a Task. Like the sample, most applications use the default TaskScheduler that accompanies the default ThreadPool. .NET supports multiple TaskShedulers and even custom TaskSchedulers. In fact the sample leverages the default TaskScheduler and a second TaskScheduler designed for applications built on WPF. I'll discuss the second TaskScheduler later in the article.

Developers accustomed to using the Asynchronous Programming Model (APM); probably wondered why it was not used in the sample. There was no point to leveraging APM. TPL capabilities covered what was previously done using APM.

The results of the simulated work Task is joined to the User Interface update with a call to the ContinueWith method. ContinueWith creates a Continuation.

Continuations

A complete explanation of Continuations is beyond the scope of this article. You can find more information on Continuations in this article on 'Microsoft .NET Framework 4.0 Task Parallel Library Continuations'.

I think of a Continuation as a way to link the results of one executing Task to the results of another Task, much the way a developer makes a callback when a dependent operation completes. ContinueWith has a variety of overloads. The sample utilizes an overload that would commonly be selected for doing work that updates the User Interface.

The first part of the sample ContinueWith overload accepts an Action tied to a Task class. With access to the sample workload target Task class, the update UI code retrieves the result of the Task class. The Result is a string containing the DateTime information.

The second parameter in the ContinueWith overload accepts a TaskScheduler. The sample gets a TaskScheduler tied to the SynchronizationContext.

SynchronizationContext

Earlier I mentioned that there was a reason for dividing the work into two Tasks. WPF UI elements can only be updated from the Thread they were created in. This is called Thread Affinity. The default TaskScheduler executes Tasks on Threads in the ThreadPool. Because of Thread Affinity the UI update Task had to execute on the Thread attached to the WPF DispatcherSynchronizationContext.

A complete explanation of the Dispatcher and the underlying WPF SchronizationContext is beyond the scope of this article, but you'll find more information among the resources at the end of the article.

Task.Start hands the Task off to TPL and the appropriate scheduler.

If all the additional TPL code seemed a bit heavy; rest assured a better way is in the works.

Async - The Future

Coming in future versions of C# and VB.NET are Asyc keywords that accomplish what was done in the sample code with a few additional lines of code beyond the synchronous example. You can read more about how to do what the new Async language features in this article on 'Awaiting Future C# Asynchronous Features Brought to you by .NET Parallel Computing'.

Conclusion

Windows Presentation Foundation made the power of DirectX more widely available to .NET developers. Task Parallel Library has made asynchronous coding more accessible to .NET developers. Using new TPL techniques and classes like Continuations and TaskSchedulers, a developer can execute WPF code asynchronously without relying on the Asynchronous Programming Model.

Resources

"Task Schedulers"

"It's all About the SynchronizationContext"

"Build More Responsive Apps with the Dispatcher"



About the Author

Jeffrey Juday

Jeff is a software developer specializing in enterprise application integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server. Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security. Jeff is a Microsoft BizTalk MVP. Jeff spends his spare time with his wife Sherrill and daughter Alexandra.

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds