Quickstart Guide

First beta release is a homemade implementation of the features in the Task Parallel Library.

There are two distinct ways of using the library. One is reletively easy to refactor into exsting code, as it allows you to write much the same as if you were not writing parallel code, the other offers better performance.

The easiest way to use ParallelTasks, is with the static methods provided by the Tasked class. This class provides method to create and start a task or future, and methods to perform for, foreach, and while loops in parallel.

Example 1:
You have a method that you want to run asyncronously:

// sequential call
DoWork();
// asyncronous call
Tasked.Do(DoWork);

The Tasked.Do() method returns a DelegateTask object. You can keep a reference, and call Wait() when you need the task to be completed. Wait() will cause the calling thread to block until the task is complete (this task, or other tasks, may be executed in the Wait() call).

// Start some work to do on another processor (if available)
Task work = Tasked.Do(DoWork);
// Do something else while the task is being processed
DoSomethingElse();
// I need the task to be done here before I can continue, so Wait() on it.
task.Wait();

Generic overloads for Do() allow you to start methods that take a single parameter.

There are also overloads for Tasked.Do() which return a Future<T>. A future accepts a method that returns a value, and stores the result in the futures' Result property. This property can be read at any time after the future is started, as the task will be waited upon if it is not already complete.

Example 2:
You have a loop which goes though an array of AI units, and calls Update() on each one. You realize that each AIs' update call is independent of each other, and could be done in parallel.

// Original sequential loop.
for (int i = 0; i < units.Length; i++)
{
	units[i].Update();
}
// New parallel loop.
Tasked.For(0, units.Length, delegate (int i)
{
	units[i].Update();
});

On a single core, the loop will just behave like the sequential loop. If you have 2 cores, and the second core is not busy, the loop will be executed by both cores, with each core taking some of the iterations. This is automatically load balanced. If one iteration takes a very long time, another core will continue to process any remaining iterations.

You have probably noticed those delegates. The methods in Tasked may be easy to use, but do not give the best performance due to the delegates and heap allocations made every call.

The more involved way to use the library is to create your own Task classes, and override the PerformAction method.

Example 3:
class AiTask : Task
{
	AI unit;
	
	public AITask(AI unit)
	{
		this.unit = unit;
	}
	
	protected override PerformAction()
	{
		unit.Update();
	}
}

You would instantiate one of these tasks for each AI when your game loads, and call Start() on each one when you want the tasks to begin processing. You can register with the Completed event, or call Wait() when you need the task to be complete.

A task can be re-started once it has completed, or been cancelled (by calling Cancel()).

Custom task classes allow you to avoid the delegate calls and extra allocations associated with the static Tasked methods.


ParallelTasks makes writing parallel code easier, but you still need to be careful that what goes on in your AI.Update() method is thread-safe; meaning that updates from different AIs can run at the same time without messing with each other.

Last edited Aug 11, 2008 at 10:20 PM by Aphid, version 9

Comments

No comments yet.