Here I present my own version of a TPL and async-await tutorial demonstrating why
TPL and async-await functionality is so useful and how to apply it to some
well-known problems.

The Purpose of TPL and async-await Features

TPL and async-await features simplify dealing with asynchronous calls. There maybe several
reasons to have asynchronous calls in your code.

Most software products, do not act in a vacuum - they has to contact other
systems. The common examples of the need for such communications are
UI or web client contacting the server to read or update some data or the middleware contacting the
databases, etc.

When such communications occur, the software on the client side cannot control or predict the speed of the
response from the server. If the client sends a synchronous request to the server, the calling thread
blocks until the server response is obtained and processed. Such blockage can lead to e.g. GUI or
web application freezing completely for an unspecified period of time - which is definitely not
desirable.
On the positive side, however, the synchronous calls, preserve the program structure - calling
the server synchronously is as easy (from the developer's point of view) as making a local call.

We can also solve the communication problem by using asynchronous communications with the server.
Most common way to do it, is to register a callback on the client to fire when the server
returns information, then to send an asynchronous request to the server - a request that does not block
the current thread. After the server responds, the callback code will update the client
based on the information obtained from the server.
The problem with this approach is that the flow of the code is broken into two different pieces -
the code before the call to the server and the callback code that runs after the server responds.
In other words - async calls to the server dramatically change the structure of the code. When you
need to make only one call to the server at a time, you can still handle the situation somehow at the
expense of making the code a little worse - having two functions per call as described above,
but what if you need to have multiple calls to the server - some running in parallel, some sequential,
some have to be executed only after a number of previous asynchronous calls have completed. Asynchronous
programming in that case can easily lead to a developer's nightmare - more and more callbacks will have to be
inserted for every async call breaking the program into a bunch of pieces that have to be connected logically. Also
some of the callbacks will have to be synchronized in order to detect their completion before starting some other
processing.

There can be reasons other than calling the server for making asynchronous calls, e.g. you might want to
do some processing on different threads in order to better utilize the multiple cores on your machine
or because such processing has been built into the framework that you are using.

The purpose of TPL and the async-await features is to make the asynchronous programming almost as simple
as the synchronous programming, allowing the developers to preserve the logical structure of the code
even when it executes asynchronously.

Organization of the Article

First I provide a refresher on TPL and async-await features. Then I show how to apply them to problems
you are likely encounter - in particular to making calls to web services, scheduling mutltiple
background workers and animation storyboards.

Software Tools Used

We use Visual Studio 2012 and .NET 4.5 for creating samples for this article. The TPL features
(without async-await and some other .NET 4.5 features) can be all run
under .NET 4.0 within Visual Studio 2010.

Refresher on the TPL

For the full coverage of the TPL features, please, see the links we provided at the beginning
of the article - here we only describe the features that we consider most useful.

Tasks

TPL's basic unit of code is Task. Tasks can run, can be waited for to finish.
Tasks can have child tasks. The code can wait on multiple tasks to finish before it proceeds.
Tasks can be cancelled and their progress can be monitored.

Task can only run from start to finish once - you cannot run the same task object two times. If you
need to re-run the Task, you'll need to create another Task object
for running the same code.

By default the tasks run on a thread from a thread pool. TaskScheduler allows the developer
to customize the thread for running the task. Some tasks, that use TaskCompletionSource
do not spawn a separate thread.

Simple Task Sample

The simplest sample showing the basic task features is located under TaskSample solution. Here is its code:

// task that does not return a value
Task t1 = new Task
(
() =>
{
Thread.Sleep(1000);
Console.WriteLine("Task Completed");
}
);
// start the task
t1.Start();
// wait for the task to finish
t1.Wait();
Console.WriteLine("End of Main");
// make sure the application console window does not
// disappear when run under the VS debugger.
Console.ReadLine();

Pretty self-explanatory - we define the task to sleep for 1 second and then to print
"Task Completed" on the console. We start the task after we define it, print
"We are waiting for the task to finish" and then call Wait method to block the
main program until the task finishes.

Simple Task Throwing Exception

If the task throws an exception, such exception can be caught in the main thread by surrounding
Wait() method with try-catch clause, as shown under
TaskWithException project:

// task that does not return a value
Task t1 = new Task
(
() =>
{
Thread.Sleep(1000);
// throw an exception within a task
thrownew Exception("This is an Exception within a task");
Console.WriteLine("Task Completed");
}
);
// start the task
t1.Start();
Console.WriteLine("We are waiting for the task to finish");
// wait for the task to finish
try
{
t1.Wait();
}
catch (AggregateException e)
{
// task framework wraps the thrown exception within
// an aggregate exception
Console.WriteLine("Caught Exception " + e.InnerException.Message);
}
Console.WriteLine("End of Main");
// make sure the application console window does not
// disappear when run under the VS debugger.
Console.ReadLine();

Waiting with Timeout

Function Wait() has a version that takes timeout parameter. Such version returns
bool value set to false when the timeout occurred and true
otherwise. The corresponding sample is located under TaskWithTimeout project:

// task that does not return a value
Task t1 = new Task
(
() =>
{
// sleep for 4 seconds
Thread.Sleep(4000);
Console.WriteLine("Task Completed");
}
);
// start the task
t1.Start();
Console.WriteLine("We are waiting for the task to finish");
// wait for 2 seconds for the task to finish
bool hasNotTimedOut = t1.Wait(2000);
if (hasNotTimedOut)
{
Console.WriteLine("The task has not timed out");
}
else
{
Console.WriteLine("The task has timed out");
}
Console.WriteLine("End of Main");
// make sure the application console window does not
// disappear when run under the VS debugger.
Console.ReadLine();

The main program waits for two seconds for the task to finish and then continues.
Note that the task is not cancelled in this case - it continues after the sleep period
and "Task Completed" message is printed at the very end - after the "End of Main" message.

First, we create CancellationTokenSource. Its property Token
contains a CancellationToken object. This object is passed to the Task's
constructor.

After starting the Task, we wait 3 seconds and call Cancel()
method on the CancellationTokenSource. Within the task, we call
cancellationToken.ThrowIfCancellationRequested() method at the end of each
iteration. This method throws an OperationCanceledException if cancellation
was requested, otherwise, it does nothing. When
OperationCanceledException propagates outside of the Task's body,
it is wrapped
within AggregateException - and this is the exception that we catch within Main.

Tasks with Child Tasks

You can start a Task within another Task's body. In
that case, Task started inside another Task's body is called
the child Task and the Task in whose body the child Task
starts is called the parent Task.
A Task constructor has an override that accepts TaskCreationOptions
argument. When this argument is specified to include TaskCreationOptions.AttachedToParent
option, the created child Task becomes "attached" to its parent. This "attachment" creates
very useful dependencies between the parent and the child tasks in that:

The parent Task won't complete until all of its attached child Tasks have completed.

The parent-child Tasks create a hierarchy very similar to function stack - only here we have
child Tasks possibly executing in different threads. We call it "attached child stack".
If an attached child throws an exception, the exception will be propagated up the
"attached child stack" - wrapped by another
AggregateException at each step of its propagation.
It can be caught at any level within the "attached child stack"

A Task created within a parent Task's body without AttachedToParent
flag is called "detached". There are no dependencies between a parent Task and
its "detached" child Tasks and we are not very interested in "detached" child
Tasks.

An exception is thrown at the grand-child level and caught at the top level within
Main function. As was mentioned about, it is wrapped by a new
AggregateException as it passes each level within the "attached child stack",
so, in order to get to the original exception, we need to use InnerException
property several times: e.InnerException.InnerException.InnerException.Message.

Tasks that Return Result

If you want a Task to product some result retrieavable from the Task
itself, you can use Task<TResult> generic form of it. The generic argument
TResult specifies the type of the Task's result. Everything discussed above
still applies to such tasks. The only extra functionality available from such Tasks is
the property

TResult Task<TResult>.Result;

It blocks while the Task is running (just like Wait() method does) and it returns the
result after the Task's run is completed.

Task.WhenAll() and Task.WhenAny()

In .NET 4.5, there is an important static method on
Task class - Task.WhenAll().
It returns a Task object that completes when and only when all the
Task objects passed to it are completed.
There is a number of method overrides - some versions of the method
accept a parameter list - others an array of Task objects.
If the input Tasks return results, the Task
returned by Task.WhenAll() method can return an array of values
corresponding to the results from the individual input Task objects.

Another method Task.WhenAny() creates a Task
that waits only for one Task to complete out of many. It is used less often,
but can be quite useful in several scenarios.

There are also methods that can block the current thread's execution until a number of Tasks
is finished of one Task out of the number is finished without creating new Tasks.
These methods are Task.WaitAll(...) and Task.WaitAny(...)

ContinueWith Method

There is a Task method ContinueWith that allows to specify functionality
you want to be executed after the task is finished - a kind of a callback to the Task.

Code for testing this method is located under ContinueWithTest project.

We create Taskt2 to be the continuation of the Taskt1.
By passing TaskContinuationOptions.OnlyOnRanToCompletion
option we make the continuation only run in case the predecessor Task
ran successfully. Since in our case, the predecessor Task threw an exception,
the successor Task will never be called.

ContinueWhenAll and ContinueWhenAny

Two methods can be used to create continuation Tasks to start after a
number of predecessor Tasks are completed: Task.Factory.ContinueWhenAll(...)
and Task.Factory.ContinueWhenAny(...). In fact these two methods are very similar to
the methods WhenAll and WhenAny described above, only they were part of
.NET 4.0 while WhenAll and WhenAny were added in .NET 4.5.

Task Progress

.NET 4.5 added IProgress<T> interface and Progress<T> class to
facilitate measuring the progress of a Task or any other code. Both
accept a generic type parameter T to specify the type of the value that measures progress.
Progress<T> implicitely implements IProgress<T> interface.

IProgress<T> has method Report(T ) that should be called to report
progress. Progress<T> has an event ProgressChanged that
fires every time the progress is reported. Second argument to this event is the progress value.
An event handler can be attached to this event to handle the progress reporting.

The Taskt iterates 5 times and uses the iteration
index number i as the progress indicator (this number is passed
to IProgress<string>.Report(...) function).

ProgressChanged event handler prints the reported progress to the console.

TaskCompletionSource and Wrapping Event Based Functionality within a Task

A lot of asynchronous functionality coming as part of .NET or from some 3-rd parties is built based on
the Event-based Asynchronous Pattern (or EAP). The principle of the EAP
is that the async functionality provides
a method to start the asynchronous operation and a callback event that allows attaching a callback event
handler that will be called once the asynchronous operation completes. The client code first attaches the
callback handler to the async functionality and then calls the method to start the async operation.

Examples of such EAP functionality are BackgroundWorker, asynchronous service references
in .NET 4.0 etc.

Much of .NET 4.5 functionality has been changed to Tasks and BackgroundWorker is
all but obsolete now, but you still might come across some
instances when it is necessary to use the EAP pattern.
In such cases, it will be nice to produce Task objects out of the EAP functionality so that
you'll be able to schedule them to run in parallel or wait for a number of previous Tasks to
finish etc. In this section we show how to achieve it.

We use TaskCompletionSource class to produce Tasks that do not create their own
threading and instead use other object's asynchronous functionality.

The EAP functionality is located under MyEAPTest class. It provides function StartAsync()
that runs a method in a separate thread printing a string that is passed to it. At the end of the async
method, EAPTestCompleted event is fired:

publicstatic Task<object> ToTask(this MyEAPTest epaTest)
{
// TaskCompletionSource should always have a generic
// type argument so since we are not using any result,
// we just set the argument to be of type object and will
// pass null to indicate the task's completion
TaskCompletionSource<object> taskCompletionSource =
new TaskCompletionSource<object>(TaskCreationOptions.AttachedToParent);
Action onEpaTestCompleted = null;
onEpaTestCompleted = () =>
{
epaTest.EAPTestCompleted -= onEpaTestCompleted;
// we are setting the result to null to indicate
// the completion of the async opration
taskCompletionSource.SetResult(null);
};
epaTest.EAPTestCompleted += onEpaTestCompleted;
// start the async operation when the task is created
epaTest.StartAsync();
return taskCompletionSource.Task;
}

Note that ToTask() method described above not only creates a Task
but also starts it. In fact, it is not recommended that you create a Task out of EAP
without starting it, since the TaskCompletionSource's Task returned
will not have a valid Start method implementation, which will be confusing for the
users of the functionality. The fact that the Task starts
within the conversion ToTask
method, does not limit the use of the functionality, however, since we can always postpone
calling the ToTask until we are ready to start the Task.

Calling SetResult method on TaskCompletionSource will cause its
Task to stop blocking.
You can also use TaskCompletionSource.SetCanceled() method to throw
OperationCancelledException from the blocking methods or, you can use
TaskCompletionSource.SetException(...) method that will make the blocking method
of the TaskCompletionSource's Task to behave as if an exception was
thrown during the Task execution. In particular, if the TaskCompletionSource
was created with AttachedToParent creation option, the exception will propagate up the
"attached child stack".

Notice that there is a method RunIt()
called from Main(). Why can't we test await keyword within the Main()
method itself? The reason is that any method that has await keyword in it should be declared
with async keyword as a method that possibly introduces some asynchronous processing, while Main() is a special method that cannot be marked with async keyword.

Note, that when you run the code, the string "End of Main" is printed before "Ended the task".
This means that during the "waiting" period, the main thread is not blocked - it continues and would
have completed the program if it was not for the Console.ReadLine() call
at the end of the Main() method. This is a major difference between await
and Task.Wait() method. Indeed, change await t; line to t.Wait()
and remove async keyword from RunIt method's declaration. After that, when you
run the code, first "Ended the task" message will be printed and only later "End of Main" - meaning that
t.Wait() is blocking the main thread until the Task is completed.

The execution context assigns a thread
for the code placed after await keyword to be executed once waiting is completed.

Note that we can change the return type of RunIt() method to Task
without returning anything from the method itself. Compiler will generate the Task object
for the method itself, since the method is declared with async keyword. The Main
method can get the task and wait on it:

Because of calling Wait() method on the Task object
returned by RunIt() method, the Main() method
blocks until asynchronous processing is completed within RunIt() and
"End of Main" string is printed after "Ended the Task".

Async-Await Tests with Return Values

Code for AwaitWithReturnsTest project is very similar to that considered above,
except that the Task that we are waiting for, returns a string result
and correspondingly we use string result = await t; to assing the
result of the Task to a string:

Note, that our RunIt() function returns result of type string,
while it is decrlared to return a Task<string>. The change of the return
type happens due to the async keyword in front of the method declaration,
which wraps whatever is returned by the function within a Task.
The returned Task<string> can be used to block the Main()
thread execution until the Task finishes or to use await
keyword on it higher up the function stack.

Async-Await and Exceptions

Take a look at AWaitWithException project. File Program.cs is almost the same as that of our AwaitTest project
except that there is an exception thrown within the Task. This exception is caught
by the try-catch block around await t; line and the exception message is printed:

Note that await keyword unwraps one level of the AggregateException so that
in the case above, we catch the original Exception and not the AggregateException
object. This is another way in which async programming becomes more like the usual synchronous one.

Usage Patterns for Task and Async-Await Functionality

In this section I describe several important cases when the TPL and async-await functionality comes very handy.

Remote Service Calls using .NET 4.5

Most financial applications collect data from many different disjoint sources -
there are usually some newer databases, older databases, some data feeds etc. A single request to
read or modify financial data can include calls to multiple services (whether such request is made
from a UI or web client or from some middleware). Some of such service calls might need to be
performed in parallel in order to get all the required replies earlier, some of the service calls
might be triggered only after the results of other service calls have arrived, since their input
might depend on them. Task would be an ideal way of representing such service calls
since we can easily run multiple Task in parallel and wait on a number
of Task objects before starting other Tasks.

Services that provide Web Service interface can be
added to and accessed from .NET application as Service References
(the services themselves can be coded in Java or
C# or anything else - it does not matter as long as they are legal Web Services).
In .NET 4.5 the Service References can be configured to be accessed asynchronously as Tasks.

Solution CallingServiceViaTasksTest consists of two projects:

MockService - contains a very simple WCF service mocking a number of service calls returning
financial data.

CallingServiceViaTasksTest - contains the test client that gets mock financial data and
prints it to the console

The service contains three methods (operations) available remotely:

GetSecurityName - given a security id, it will return a security name -
in fact my mock implementation will return the same name
"MSFT" for anything you pass to it.

GetExchangesSecurityTradedOn - given security id, it will return the names of the exchanges
where this security is traded

GetSecurityExchangeData - given the security id and the exchange name it returns the price of the
security on that exchange.

Assuming that you are building this project from scratch, you can add a service reference to the client
project by right-mouse clicking the References under the client project name within solution explorer and
choosing "Add Service Reference". Set "http://localhost:20575/MockFinancialDataService.svc" to be the
service URL, then click the button "Advanced" and make sure that "Allow generation of asynchronous operations"
checkbox is clicked and the option "Generate task-based operations" is chosen under this checkbox:

If you cannot select "Generate task-based operations" - it means that your client project is not
using .NET 4.5 (most likely it uses .NET 4.0) and you need to change your framework and then
reconfigure the service reference.

This client code is also very neat and simple (due to the TPL and async-await functionality):

We request the security name and the exchanges on which it trades in parallel. Then wait
until both produce results. After that, for each of the returned exchanges,
we request the price information and print out the security name, the exchange name and the price
to the console.

Now, try to imagine implementing the code above without TPL functionality. Instead of one little
neat function, you would have at least two functions (or lambdas) per remote call. On top of that,
you would have to add a lot of code for implementing the functionality to wait for the two first
asynchronous calls to complete before calling the GetSecurityExchangeDataAsync
remote method.

Remote Service Calls using Older API

If you company has not moved to .NET 4.5 yet, you can still use write the Task
wrappers around the asynchronous service calls. Solution CallingServicesViaTasksOlderAPITest
shows how to do it. It consists of the WCF MockService project - the same as in the previous
sample and the client project.

When the service reference is configured to generate async service calls, .NET 4.0 and earlier .NET
versions will generate methods to call the service in two different
ways - Event-based Asynchronous Pattern (EAP) and
Asynchronous Programming Model (APM). We took a look at EAP above - it creates a method to start
an asynchronous operation and a callback registered to fire when the async operation completes.

APM pattern has two methods - one to start an async operation, the other to block until the
operation completes. In case of our remote services - the APM methods to start an operation start
with "Begin" prefix, while those that block till the operation completes start with "End" prefix, e.g.
service operation GetSecurityName results in two APM methods:
BeginGetSecurityName to start the operation and EndGetSecurityName to block till
operation completes.

We use the APM pattern to create Task wrappers for calling async services - it can be
achieved even easier for APM pattern than for EAP one by using Task.Factory.FromAsync<TResult>(...)
function. Here is our client code:

Task.Factory.FromAsync<TResult>(...) method creates a task around two APM methods.
After these arguments, you need to pass the input arguments to the Begin... APM method.
The last argument to FromAsync is state variable, which we do not use
and pass as null. FromAsync has a bunch of overrides allowing to enter up to three
arguments to the Begin APM function. If, however, the Begin function
has more than three arguments, you can always wrap it within a lambda expression or a delegate
that takes less than three arguments and pass this lambda expression to FromAsync.

Note, that our previous example of a service call (using .NET 4.5 functionality) will not block
the thread it runs on, e.g. the UI thread in WPF application. The current example of
using older .NET functionality, however, does block the current thread by its
Wait or WaitAll methods. So, if you do not want the thread to be blocked
by it, you can always start it on a different thread, e.g. by making it continue a Task
running on its own thread.

Wrapping a BackgroundWorker in a Task

Having Task functionality made BackgroundWorker functionality
largerly obsolete - you can achieve whatever you need using a Task instead of
a BackgroundWorker. Still there might be some reason you want to use
BackgroundWorker functionality on the team - whether because your legacy
code uses it or because most of your team members or your boss love it and understand it better
than the newer Task functionality.

Here, we show, how to wrap the BackgroundWorker within Task so that
you could gain all the flexibility of Task functionality for
BackgroundWorker based code.

Solution BackgroundWorkerTaskWrap shows how to wrap a background worker within a
Task.

The task wrapping code is located under BackgroundWorkerUtils.ToTask()
extension function. It is TaskCompletionSource based, so the resulting
task is started during the conversion.
It provides interface for Task cancellation and progress reporting:

In the sample above we schedule two background workers to run in parallel and the third one
to start when two first background workers completed their run.

Wrapping WPF Storyboards in Tasks

I always wanted be able to combine multiple storyboards, so that some of them would run in
parallel and then when they finish, some other animations would start. Task
functionality is ideal for making this happen.

The storyboard sample is located under WrappingStoryboardsInTasks project.

The XAML file of the project contains two rectangles blue and three Storyboard objects.
First two storyboard rotate correspondingly blue and red rectangle, while the 3rd one increases their width.

On pressing "Start Animation" button we want to start the first two Storyboards and
when they both finish, we want to start the 3rd one. On top of that, once the StartAnimationButton
button is clicked,
we want to disable it and re-enable it once the last animation stops in order to prevent starting
the new storyboard run in the middle of the previous one.

Here is how simple the code becomes when we use the TPL and async-await functionality:

Note that we use TaskCompletionSource to create a Task wrapper
around the Storyboards, so we should be starting
the Storyboard during the conversion.

Storyboards themselves consist of animation objects. Eventually (time permitting)
I would like to use
Task objects to wrap individual animations and built a new type of Storyboard-like
objects having different animation starting based on when the previous animations finished instead of
being time based. This would result in the animation objects that are easier to build and control.

Summary

In this article we provided information on using TPL and async-await features for creating asynchronous
functionality that is almost as simple as the synchronous code.
We showed how to apply these concepts to sending and processing numerous service requests, scheduling
multiple BackgroundWorkers and Storyboards.

Share

About the Author

I have 15 years of experience developing enterprise software, starting from C++ and Java on UNIX and moving towards C# on Windows platforms.
I am fascinated by the new .NET technologies especially WPF, Silverlight and LINQ.
Recently I decided to make a move and start my own contracting consulting and mentoring company AWebPros.
I can be contacted via my web site awebpros.com or through my blog at nickssoftwareblog.com

Comments and Discussions

[Just happened to find a discrepency in the return type in the code below
"Async-Await Tests with Return Values". The task is returning string but the method signature is Task and the same typo in main() as well].

Thanks again for putting all of these together, expect more 4.5 articles.