With .NET 4.0 a new version of the thread pool will become available. In addition to performance and load balancing enhancements, this new thread pool allows you to use Tasks. A Task is a lightweight unit of work similar to what you create when you use ThreadPool.QueueUserWorkItem. But unlike the anonymous work item, Task objects expose a powerful API. You can access this API by capturing the return value from calls to the

Task.StartNew function. This function, like those for threads, accepts a delegate or anonymous function defining what work is to be performed.

Just like full threads, tasks expose a method allowing the scheduling thread to wait for the task’s completion. The methods are Wait, WaitAny, and WaitAll, the latter two accepting a list of tasks. Waits can be absolute or can have a maximum timeout.

With waits, the waiting thread is blocked. When blocking isn’t a good option, but you still want to perform an action when the current task(s) are complete, you can use continuations. A continuation in this context is a operation that is scheduled to be performed when the task or set of tasks are completed. To schedule a follow-up task, you can call the ContinueWith, ContinueWithAll, or ContinueWithAny function and pass it a delegate. This function can be called multiple times, effectively creating a pipeline of operations.

Cancellation is one area that .NET does not currently support very well. There is no way to remove unneeded tasks from the current thread pool and thread aborts are considered to be very dangerous. With .NET 4, cancellation of tasks becomes a first class citizen. When a task that has not been started is cancelled, it is removed from the queue immediately. If the task has begun, cooperation with the operation is needed. The delegate that actually performs the task’s work needs to periodically check the IsCancellationRequested property and respond appropriately.

Tasks have another feature not seen before in .NET, it supports parent-child relationships. This allows complex tasks to be broken into smaller parts but still be seen as a single logical operation. This offers significant advantages for supporting things such as cancellation. When a parent task is cancelled, child tasks are optionally cancelled as well.

Futures are tasks that execute a function asynchronously. When the result of the function is needed, the Future checks to see if the function has completed. A value is returned if it is done processing, what happens if it is not done depends on the implementation.

For example, Reading the Value property will cause the thread to block until the task is complete. Like other tasks, you have access to the IsCompleted property and the Wait, ContinueWith, and Cancel methods. This added functionality makes .NET futures more powerful than the textbook description and arguably not a future at all. For this reason, among others, .NET 4.0 futures have been renamed Task<T> where T is the return type.

It should be noted that Tasks in .NET are not constrained to thread-safe operations. There is nothing preventing, say a future that calculates a derivative, from also changing a global variable. This means normal locking and object ownership rules still apply, though of course these can be minimized by exclusively using immutable objects.

Wow. I must say - that once I learned how to use Executors, and Futures in the new(er) Java concurrency package - multi-threaded programming became much more manageable. Obviously you still have synchronization issues around global state - but at least how many threads you have and what they are doing becomes more straight-forward.

InfoQ Weekly Newsletter

Join a community of over 250 K senior developers by signing up for our newsletter. If you are based in the EEA, please contact us so we can provide you with the protections afforded to you under EEA protection laws.

Is your profile up-to-date? Please take a moment to review and update.

Email Address

Note: If updating/changing your email, a validation request will be sent

Company name:

Keep current company name

Update Company name to:

Company role:

Keep current company role

Update company role to:

Company size:

Keep current company Size

Update company size to:

Country/Zone:

Keep current country/zone

Update country/zone to:

State/Province/Region:

Keep current state/province/region

Update state/province/region to:

Subscribe to our newsletter?

Subscribe to our architect newsletter?

Subscribe to our industry email notices?

You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.

We notice you're using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.