Community, Parallelisation Talk Examples, Parallelization Talk Examples, Talk Examples

DDD South West Parallelisation Talk Overview

Examples

Here are all the examples from Saturday’s introductory talk on Parallelisation at DDD South West 2011.

Slide Deck

The slide deck is also available as a PDF file (15.9 Mb)

Community, Parallelisation Talk Examples, Parallelization Talk Examples, Talk Examples

Parallelisation Talk examples – Cancelling Tasks

This example showed what happens when tasks are cancelled. In this example, some tasks will be able to run to completion, others will be cancelled and other won’t even get a chance to start because the cancellation token was signalled before the task gets a chance to start.

Here is the code for the cancellation example shown in the talk

class Program
{
    static void Main(string[] args)
    {
        const int numTasks = 9;

        // Set up the cancellation source and get the token.
        CancellationTokenSource tokenSource = new CancellationTokenSource();
        CancellationToken token = tokenSource.Token;

        // Set up the tasks
        Task[] tasks = new Task[numTasks];
        for (int i = 0; i < numTasks; i++)
            tasks[i] = Task.Factory.StartNew(() => PerformTask(token), token);

        // Now the tasks are all set up, show the state.
        // Most will be WaitingToRun, some will be Running
        foreach (Task t in tasks.OrderBy(t => t.Id))
            Console.WriteLine("Tasks {0} state: {1}", t.Id, t.Status);

        // Give some of the tasks a chance to do something.
        Thread.Sleep(1500);

        // Cancel the tasks
        Console.WriteLine("Cancelling tasks");
        tokenSource.Cancel();
        Console.WriteLine("Cancellation Signalled");

        try
        {
            // Wait for the tasks to cancel if they've not already completed
            Task.WaitAll(tasks);
        }
        catch (AggregateException aex)
        {
            aex.Handle(ex =>
            {
                // Handle the cancelled tasks
                TaskCanceledException tcex = ex as TaskCanceledException;
                if (tcex != null)
                {
                    Console.WriteLine("Handling cancellation of task {0}", tcex.Task.Id);
                    return true;
                }

                // Not handling any other types of exception.
                return false;
            });
        }

        // Show the state of each of the tasks.
        // Some will be RanToCompletion, others will be Cancelled.
        foreach(Task t in tasks.OrderBy(t => t.Id))
            Console.WriteLine("Tasks {0} state: {1}", t.Id, t.Status);


        Console.WriteLine("Program End");
        Console.ReadLine();
    }

    static void PerformTask(CancellationToken token)
    {
        try
        {
            // The loop simulates work that can be cooperatively cancelled.
            Console.WriteLine("Task {0}: Starting", Task.CurrentId);
            for (int i = 0; i < 4; i++)
            {
                // Check for the cancellation to be signalled
                token.ThrowIfCancellationRequested();

                // Write out a little bit showing the progress of the task
                Console.WriteLine("Task {0}: {1}/4 In progress", Task.CurrentId, i + 1);
                Thread.Sleep(500); // Simulate doing some work
            }
            // By getting here the task will RunToCompletion even if the
            // token has been signalled.
            Console.WriteLine("Task {0}: Finished", Task.CurrentId);
        }
        catch (OperationCanceledException)
        {
            // Any clean up code goes here.
            Console.WriteLine("Task {0}: Cancelling", Task.CurrentId);
            throw; // To ensure that the calling code knows the task was cancelled.
        }
        catch(Exception)
        {
            // Clean up other stuff
            throw; // If the calling code also needs to know.
        }
    }
}

 

Here is the output of the program (your results may vary):

Task 1: Starting
Task 1: 1/4 In progress
Task 2: Starting
Task 2: 1/4 In progress
Tasks 1 state: Running
Task 3: Starting
Task 3: 1/4 In progress
Tasks 2 state: Running
Task 4: Starting
Task 4: 1/4 In progress
Tasks 3 state: Running
Tasks 4 state: Running
Tasks 5 state: WaitingToRun
Tasks 6 state: WaitingToRun
Tasks 7 state: WaitingToRun
Tasks 8 state: WaitingToRun
Tasks 9 state: WaitingToRun
Task 1: 2/4 In progress
Task 2: 2/4 In progress
Task 3: 2/4 In progress
Task 4: 2/4 In progress
Task 1: 3/4 In progress
Task 2: 3/4 In progress
Task 4: 3/4 In progress
Task 3: 3/4 In progress
Task 1: 4/4 In progress
Task 2: 4/4 In progress
Task 4: 4/4 In progress
Task 3: 4/4 In progress
Task 5: Starting
Task 5: 1/4 In progress

To this point the tasks have been given a chance to operate normally. The tasks that have started are outputing to the console their progress. The main thread reports on the state of the tasks and shows tasks 1 to 4 are Running while the remainder are WaitingToRun. After a while the scheduler decides to start task 5.

Next the tasks are going to be cancelled.

Cancelling tasks
Cancellation Signalled
Task 1: Finished
Task 2: Finished
Task 4: Finished
Task 3: Finished
Task 5: Cancelling

When the cancellation token is signalled the tasks have to cooperate. Tasks 1 to 4 are too far gone and will run to completion. Task 5, which was only just started, cooperates with the cancellation request and writes that it is cancelling. No waiting tasks are started.

In the main thread, the control is blocked until all the tasks have either finished or cooperate with the cancellation request. Once the WaitAll unblocks the program handles any cancelled tasks in the catch block.

Handling cancellation of task 9
Handling cancellation of task 8
Handling cancellation of task 7
Handling cancellation of task 6
Handling cancellation of task 5

Tasks 6 to 9 never got a chance to start. Task 5 was started, but was cancelled. Therefore task 5’s cancellation can be handled inside the task and outside it. Different clean up may be required in each place.

Finally, the program lists the end state (See also: Task state transitions) of each of the tasks:

Tasks 1 state: RanToCompletion
Tasks 2 state: RanToCompletion
Tasks 3 state: RanToCompletion
Tasks 4 state: RanToCompletion
Tasks 5 state: Canceled
Tasks 6 state: Canceled
Tasks 7 state: Canceled
Tasks 8 state: Canceled
Tasks 9 state: Canceled
Program End

When writing code to handle cancelled tasks, watch out for this gotcha that can trip you up if you are not careful.

Community, Talk Follow-up

Feedback from my DDD Scotland Talk on Parallisation

DDD Scotland 2011 Talk Opening SlideI got my feedback from my DDD Scotland 2011 talk on Parallelisation. I was actually pleasantly surprised. I guess I was being a little too self critical and the talk went over a lot better than I thought it had.

Some of the highlights:

  • Good clear samples and demos.
  • Enthusiastic speaker who really knew his stuff. Great talk!
  • Nice easy to understand examples. Getting the concepts across without clutter.
  • Useful info. Genuinely learnt something new.

And of course my favourite comment (despite being somewhat irrelevant, or should that be irreverent): Colin’s funky hair.

There were a couple of points that I need to address in future versions of the talk.

I only gave an overview of locking and the only demo that went close was the ConcurrentDictionary example in which all the locking mechanisms are internal to the ConcurrentDictionary. One person wanted more detail on locking so I shall endeavour to add a little extra into the presentation for DDD South West on locking including, if time allows, a specific demo.

The aspect of locking I need to address, is that I talked about when I used a semaphore in a project to restrict access to a scarce resource, but again I didn’t elaborate on it and another person would have found an example of a semaphore being used useful. I have already written about semaphores in a previous blog post, so I shall try and work that in to the next version of the presentation.

The other part is that the intro appears to be a little long and I need to shorten than slightly. If I can do that, it will at least free up space in a one hour talk to add the additional information on locking in later on.

I really appreciate the additional few moments people took at the end of my talk to write specifically what they enjoyed and what they disliked about my presentation, especially as lunch was waiting for them. It really gives me something to work with in order to improve the talk.

Community

DDD South West 3

I’ll be speaking at DDD South West 3 this year. My talk on Parallelisation (“Parallel… Parallelise… Pallar… Doing stuff at the same time in .NET 4.0”) was voted onto the agenda.

.NET 4 has some very nifty features to aid the creation of multiple threads of operation. In this talk I’ll be introducing those features and demonstrating what they can do for you, how you can benefit… And importantly, what you shouldn’t do if you want to maintain your sanity. I’ll also be doing my best work out how to correctly pronounce "parallelisation" by DDD South West.

If you are interested in an introduction to Parallelisation in .NET 4 then it would be a great opportunity to learn more about it.

Incidentally, if you can’t make it to Bristol I’ll be doing the talk at DDD Scotland 2011 in May. And if you can’t wait at all then just check out the Parallelisation tag on my blog for a number of articles on the subject or the overview from the talk I did at Scottish Developers last night.