Aberdeen Developers – Introduction to Parallelisation

Examples

Here are all the examples from Thursday evening’s introductory talk on Parallelisation at the Aberdeen Developers User Group.

Slide Deck

You can download the slide deck here.

DDD Belfast Parallelisation Talk

Examples

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

Slide Deck

You can download the slide deck here.

SQL Server User Group: SQL Injection Attacks

Examples

The examples were run against a copy of the Adventure Works database.

Required Tables

For the Second Order Demo you need the following table added to the Adventure Works database:

CREATE TABLE [dbo].[FavouriteSearch](
	[id] [int] IDENTITY(1,1) NOT NULL,
	[name] [nvarchar](128) NOT NULL,
	[searchTerm] [nvarchar](1024) NOT NULL
) ON [PRIMARY]

GO

Stored Procedure with dynamic SQL

This is the stored procedure from the last demo which shows the Stored Procedure dynamically building a SQL statement that is susceptible to a SQL Injection Attack.

CREATE procedure [dbo].[SearchProducts]
(
  @searchId int
)
AS
BEGIN

  DECLARE @searchTerm NVARCHAR(1024)
  SELECT @searchTerm = searchTerm FROM FavouriteSearch WHERE id = @searchId

  DECLARE @sql NVARCHAR(2000) =
  'SELECT ProductID, Name, ProductNumber, ListPrice
  FROM Production.Product
  WHERE DiscontinuedDate IS NULL
  AND ListPrice > 0.0
  AND Name LIKE ''%'+@searchTerm+'%''';

  EXEC (@sql);

END

 

Slide Deck

The slide deck is available for download.

Further Reading

During the talk I mentioned this lesson from history (why firewalls are not enough), I also showed XKCD’s famous “Bobby Tables” cartoon, and also a link to further information on dynamic SQL in Stored Procedures. More information about the badly displayed error messages can be found amongst two blog posts: What not to develop, and a follow up some months later.

I wrote an article on SQL Injection Attacks that you can read here.

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)

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.

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.

DDD Scotland Parallelisation Talk Overview

DDD Scotland 2011 Talk Opening Slide

Follow Up

I was asked a question during the talk I wasn’t immediately able to answer which I’ve now found the definite answer. What happens to parallel tasks running in the background when the application exits?

Examples

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

Slide Deck

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

Background tasks and application exit

During my talk on Parallelisation at DDD Scotland 2011 I was asked what happens if the application finishes while there were still tasks running.

At the time, I was showing the Tasks Within Tasks demo and I showed what happened when the Wait call was removed in the Main method. Since the Wait call was removed the lines following it were immediately executed. Those were: to output that the program was ending; and to wait for a key press (to give the audience time to read the console output).

So, what happens when the application naturally concludes like when the Main method completes? When preparing the talk that question had simply not occurred to me. Do the background tasks continue until completion or do they all stop? I suspected they would just stop.

During the talk I simply removed the Console.ReadLine call, but then the console window appeared and then disappeared in a tiny fraction of a second. Did the tasks stop? Or, did the tasks simply continue without a console window available?

Since a further investigation at the time would have disrupted the talk I said I’d investigate further and follow up on my blog. So, this is that follow up.

I’ve now created a new example where the tasks output to files rather than the console. If the tasks stop, the files either won’t be created or contain incomplete output. If they are allowed to continue then the files will be complete.

Here is the code:

class Program
{
    private static readonly string folderName = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");

    static void Main(string[] args)
    {
        // Create a directory for the output to go.
        Directory.CreateDirectory(folderName);

        // Start the tasks
        for (int i = 0; i < 20; i++)
            Task.Factory.StartNew(PerformTask, TaskCreationOptions.AttachedToParent);

        // Give the tasks a chance to start something.
        Thread.Sleep(750);
    }

    public static void PerformTask()
    {
        // Create a new file in the output directory
        string path = folderName + "\" + Task.CurrentId + ".txt";
        using (StreamWriter writer = File.CreateText(path))
        {
            // Ensures that all write operations are immediately flushed to disk
            writer.AutoFlush = true;

            // Write stuff to the file over a period of time
            writer.WriteLine("Starting Task {0}", Task.CurrentId);
            Thread.Sleep(500);
            writer.WriteLine("Ending Task {0}", Task.CurrentId);
        }
    }
}

In the Main method, the Sleep waits long enough that the first few tasks will run to completion and further queued tasks are started.

The result on my machine is that the first 4 tasks run to completion, the next 4 tasks are in still being processed when the Main method naturally concludes. At this point the application exits. All the running tasks are forced to exit leaving files with only the first part of their content in them.

So, in answer to the question I was asked: If the application finishes while there are tasks still running then all the running tasks are all stopped without being allowed to complete. No more queued tasks are started.

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.