Software Development

Handling AggregateExceptions

I’ve written a couple of posts (see also) about how the AggregateException plays its part in exception handling in parallel systems. However, it has another trick up its sleeve when it comes to handling exceptions.

AggregateException has a Handle method that takes a delegate of Func<Exception, bool> i.e. It takes an Exception as a parameter and returns a bool. The return value indicates whether the function handled the exception or not.

Here is an example program that shows what how it works.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            DoWork();
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("Handle Remaining Exceptions");
            foreach(Exception ex in aex.InnerExceptions)
            {
                Console.WriteLine("{0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        Console.ReadLine();
    }

    private static void DoWork()
    {
        const int numTasks = 20;
        Task[] tasks = new Task[numTasks];
        for (int i = 0; i < numTasks; i++)
            tasks[i] = Task.Factory.StartNew(PerformTask);

        Thread.Sleep(2500);

        try
        {
            Task.WaitAll(tasks);
        }
        catch(AggregateException aex)
        {
            Console.WriteLine("AggregateException.Handle...");
            aex.Handle(ex => HandleException(ex));
            Console.WriteLine("Finished handling exceptions."); // This never shows
        }
    }

    public static bool HandleException(Exception ex)
    {
        if (ex is OddException)
        {
            Console.WriteLine("Handling: {0}", ex.Message);
            return true;
        }

        Console.WriteLine("Not handling: {0}", ex.Message);
        return false;
    }

    public static void PerformTask()
    {
        int? id = Task.CurrentId;
        Console.WriteLine("Performing Task {0}", id);

        if (id.Value % 13 == 0)
            throw new TriskaidekaException("Mwaaahaahaahaahaaaaaaaa!");

        if (id.Value % 2 == 1)
            throw new OddException("The task ("+id+") is distinctly odd.");
    }
}

The program starts 20 tasks (DoWork). Each task (PerformTask) simply outputs a line to the console to say what it’s id is and then throws an exception depending on some condition. There are two types of exception that it can throw.

Back in the main thread (DoWork) a Sleep statement gives the tasks a chance to get going (and hopefully complete). During this time, the tasks get the opportunity to output the following.

Performing Task 1
Performing Task 2
Performing Task 4
Performing Task 3
Performing Task 5
Performing Task 8
Performing Task 9
Performing Task 10
Performing Task 12
Performing Task 13
Performing Task 6
Performing Task 14
Performing Task 7
Performing Task 16
Performing Task 17
Performing Task 18
Performing Task 15
Performing Task 11
Performing Task 19
Performing Task 20

Then the Task.WaitAll statement is called which will potentially throw an AggregateException (in fact it will with 10 InnerExceptions).

Since the Task.WaitAll call is wrapped in a try/catch the AggregateException is caught. We output a message to say the exceptions are being handled. The AggregateException.Handle method calls the method given (HandleException) once for each of the InnerExceptions.

AggregateException.Handle...

The HandleException method either handles the exception (in which case it returns true) or it doesn’t (so returning false). In each case it also writes to the console to say what it has done. That console output looks like this:

Handling: The task (19) is distinctly odd.
Handling: The task (17) is distinctly odd.
Handling: The task (15) is distinctly odd.
Not handling: Mwaaahaahaahaahaaaaaaaa!
Handling: The task (11) is distinctly odd.
Handling: The task (9) is distinctly odd.
Handling: The task (7) is distinctly odd.
Handling: The task (5) is distinctly odd.
Handling: The task (3) is distinctly odd.
Handling: The task (1) is distinctly odd.

The AggregateException.Handle method then checks to see if any of the exceptions remain unhandled. If there are still unhandled exceptions then it rethrows. Since there is one remaining exception that is unhandled the line of code after the call to Handle is never called.

The try/catch block in the Main method catches AggregateException and just loops over the remaining exceptions to show what was left unhandled.

Handle Remaining Exceptions
TriskaidekaException: Mwaaahaahaahaahaaaaaaaa!

See also

Software Development

Tasks that throw exceptions

I’ve blogged before about the AggregateException in .NET 4, but I missed out something that may be important. If you are using Parallel.Invoke or Parallel.For or Parallel.ForEach or PLINQ you probably won’t notice this because each of these constructs block until all the tasks are completed. However, if you are using Task.Factory.StartNew() then this may be important.

The AggregateException won’t bubble up into the calling thread or task until one of the Wait… methods (excluding WaitAny) is called.

This means that any number of exceptions can be happening but the thread that starts the task may not know about it for some time if it is getting on with other things itself.

Take this code for example:

class Program
{
    static void Main(string[] args)
    {
        // Start the tasks
        List<Task> tasks = new List<Task>();
        for (int i = 0; i < 20; i++)
        {
            Task t = Task.Factory.StartNew(PerformTask);
            tasks.Add(t);
        }

        Console.WriteLine("Press enter to display the task status.");
        Console.ReadLine();

        // Display the status of each task.
        // If it has thrown an exception will be "faulted"
        foreach(Task t in tasks)
            Console.WriteLine("Task {0} status: {1}", t.Id, t.Status);

        Console.WriteLine("Press enter to wait for all tasks.");
        Console.ReadLine();

        // This is where the AggregateException is finally thrown
        Task.WaitAll(tasks.ToArray());

        Console.ReadLine();
    }

    public static void PerformTask()
    {
        Console.WriteLine("Starting Task {0}", Task.CurrentId);
        throw new Exception("Throwing exception in task "+Task.CurrentId);
    }
}

At the start of the program it starts 20 tasks, each of which throws an exception. The output of the program at this point is:

Press enter to display the task status.
Starting Task 2
Starting Task 1
Starting Task 4
Starting Task 3
Starting Task 5
Starting Task 7
Starting Task 6
Starting Task 8
Starting Task 9
Starting Task 10
Starting Task 11
Starting Task 12
Starting Task 13
Starting Task 14
Starting Task 15
Starting Task 17
Starting Task 16
Starting Task 18
Starting Task 19
Starting Task 20

The reason the "Press enter to display the task status" appears on the first line is that the main thread is still running and performing operations as the background tasks are still spinning up.

Then each of the tasks are started and each output a simple line to the console to prove they are there. Then each throws an exception, so far unseen (other than for the debugger breaking the running on the program to tell the developer, but in a production system you are not going to have that.)

Now, the application is paused on a Console.ReadLine() waiting for the user to press enter. The application is still running merrily.

If the enter key is pressed the next bit of output is displayed:

Task 1 status: Faulted
Task 2 status: Faulted
Task 3 status: Faulted
Task 4 status: Faulted
Task 5 status: Faulted
Task 6 status: Faulted
Task 7 status: Faulted
Task 8 status: Faulted
Task 9 status: Faulted
Task 10 status: Faulted
Task 11 status: Faulted
Task 12 status: Faulted
Task 13 status: Faulted
Task 14 status: Faulted
Task 15 status: Faulted
Task 16 status: Faulted
Task 17 status: Faulted
Task 18 status: Faulted
Task 19 status: Faulted
Task 20 status: Faulted
Press enter to wait for all tasks.

This time the "Press enter to wait for all tasks." message appears at the end of the list. This is because everything here is being written from the main thread.

As you can see everything is "Faulted" meaning that an exception was thrown. Yet, still the application is proceeding merrily along the main thread

Finally, the enter key is pressed and the Task.WaitAll() method is called…. And the main thread only how has all those exceptions to contend with (in the form of an AggregateException)

Throw on WaitAll

That’s a bit of a gotcha if you don’t know where the AggregateException is coming from.

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, Parallelisation Talk Examples, Parallelization Talk Examples, Talk Examples

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)

Community, Software Development, Talk Follow-up

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.

Parallelisation Talk Examples, Parallelization Talk Examples, Talk Examples

Parallelisation Talk Example – Aggregate Exceptions

The two code examples here show what happens when exceptions are thrown within tasks that are not handled within the task. In each case the task that has the error throws an exception.

In the first example, only one task throws an exception. Although from the output you can see that more tasks were expected to be launched the framework no longer schedules tasks to be started once an exception is thrown. Any existing tasks are continued to completion.

In the second example, all the tasks will throw exceptions. This is just to show that the aggregate exception is bringing back all the exceptions from the various tasks that were running.

Code Example 1 : Some bad

class Program
{
    static void Main(string[] args)
    {
        List<HotelRoomAvailability> hotelList = GetHotels();

        Console.WriteLine("These are the hotels to process");
        foreach(var hotel in hotelList)
            Console.WriteLine(hotel.HotelCode);

        Console.WriteLine(new string('=',79));


        try
        {
            Parallel.ForEach(hotelList, item => PopulateDetails(item));
        }
        catch (AggregateException aggex)
        {
            Console.WriteLine(aggex.Message);
            foreach(Exception ex in aggex.InnerExceptions)
                Console.WriteLine(ex.Message);
        }


        Console.WriteLine("Program finished");
        Console.ReadLine();

    }

    private static void PopulateDetails(HotelRoomAvailability hotel)
    {
        Console.WriteLine("Populating details of {0}", hotel.HotelCode);
        hotel.Name = HotelRespository.GetHotelName(hotel.HotelCode);
        hotel.Rates = AvailabilityRespository.GetRateInformation(
            hotel.HotelCode, hotel.StayDate, hotel.NumberOfNights);
    }

    private static List<HotelRoomAvailability> GetHotels()
    {
        List<HotelRoomAvailability> result = new List<HotelRoomAvailability>
            {
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONSOHO"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONLHRT4"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONLHRT5" // Not valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONWATERL" // Not valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONLHR123"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONCOVGDN"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONCTYAIR"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONLEISQR"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONPADDIN" // Not Valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONHIGHOL"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONKINGSX"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONEUSTON"
                    }
            };

        return result;
    }
}

Output

The following is output first

These are the hotels to process
LONSOHO
LONLHRT4
LONLHRT5
LONWATERL
LONLHR123
LONCOVGDN
LONCTYAIR
LONLEISQR
LONPADDIN
LONHIGHOL
LONKINGSX
LONEUSTON
========================================================
Populating details of LONSOHO
Populating details of LONWATERL
Populating details of LONCTYAIR
Populating details of LONHIGHOL
Populating details of LONLHRT4

 

Aggregate Exception Example - Before

Then an exception is thrown

Aggregate Exception Example - Exception Assistant

And the final output looks like this:

These are the hotels to process
LONSOHO
LONLHRT4
LONLHRT5
LONWATERL
LONLHR123
LONCOVGDN
LONCTYAIR
LONLEISQR
LONPADDIN
LONHIGHOL
LONKINGSX
LONEUSTON
========================================================
Populating details of LONSOHO
Populating details of LONWATERL
Populating details of LONCTYAIR
Populating details of LONHIGHOL
Populating details of LONLHRT4
One or more errors occurred.
The hotel code 'LONWATERL' does not match a known hotel
Program finished

 

Aggregate Exception Example - After

Code Example 2 : All bad

This example replaces the GetHotels method, above, with a method that creates a list of entirely non-existant hotels:

class Program
{
    static void Main(string[] args)
    {
        List<HotelRoomAvailability> hotelList = GetHotels();

        Console.WriteLine("These are the hotels to process");
        foreach(var hotel in hotelList)
            Console.WriteLine(hotel.HotelCode);

        Console.WriteLine(new string('=',79));


        try
        {
            Parallel.ForEach(hotelList, item => PopulateDetails(item));
        }
        catch (AggregateException aggex)
        {
            Console.WriteLine(aggex.Message);
            foreach(Exception ex in aggex.InnerExceptions)
                Console.WriteLine(ex.Message);
        }


        Console.WriteLine("Program finished");
        Console.ReadLine();

    }

    private static void PopulateDetails(HotelRoomAvailability hotel)
    {
        Console.WriteLine("Populating details of {0}", hotel.HotelCode);
        hotel.Name = HotelRespository.GetHotelName(hotel.HotelCode);
        hotel.Rates = AvailabilityRespository.GetRateInformation(
            hotel.HotelCode, hotel.StayDate, hotel.NumberOfNights);
    }

    private static List<HotelRoomAvailability> GetHotels()
    {
        List<HotelRoomAvailability> result = new List<HotelRoomAvailability>
            {
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "BRISTOL"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "BIRMINGHAM"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "MANCHESTER" // Not valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LIVERPOOL" // Not valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "CARLISLE"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "CAMBRIDGE"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "OXFORD"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "READING"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LEEDS" // Not Valid
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "NEWCASTLE"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "EDINBURGH"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "GLASGOW"
                    }
            };

        return result;
    }
}

Output

These are the hotels to process
BRISTOL
BIRMINGHAM
MANCHESTER
LIVERPOOL
CARLISLE
CAMBRIDGE
OXFORD
READING
LEEDS
NEWCASTLE
EDINBURGH
GLASGOW
============================================================
Populating details of BRISTOL
Populating details of LIVERPOOL
Populating details of OXFORD
Populating details of NEWCASTLE
Populating details of BIRMINGHAM
One or more errors occurred.
The hotel code 'LIVERPOOL' does not match a known hotel
The hotel code 'OXFORD' does not match a known hotel
The hotel code 'NEWCASTLE' does not match a known hotel
The hotel code 'BIRMINGHAM' does not match a known hotel
The hotel code 'BRISTOL' does not match a known hotel
Program finished

More Information

Parallelisation Talk Examples, Parallelization Talk Examples, Talk Examples

Parallelisation talk example – Independent Object Graphs

Parallelised code works best when data is not shared. This example shows a simple piece of parallel code where each task operates independently on its own object graph without dependencies on other objects outside its own graph.

Each iteration of the Parallel.ForEach statement operates on only one item in the List named initialObjectGraph. The operations do not make reference to any other objects in the list. The PopulateDetails method (which effectively operates on each item in the list) only uses and updates the information in just that one item.

The program outputs the initial object graph with just the very basic information that is input into it in the GetObjectGraph method. After the Parallel.ForEach has called PopulateDetails on each element in the list, the object graph is output once again

Example Code

class Program
{
    static void Main(string[] args)
    {
        List<HotelRoomAvailability> initialObjectGraph = GetObjectGraph();

        DisplayObjectGraph(initialObjectGraph);

        Parallel.ForEach(initialObjectGraph, item => PopulateDetails(item));

        DisplayObjectGraph(initialObjectGraph);

        Console.WriteLine("Program finished");
        Console.ReadLine();

    }

    private static void PopulateDetails(HotelRoomAvailability hotel)
    {
        Console.WriteLine("Populating details of {0}", hotel.HotelCode);
        hotel.Name = HotelRespository.GetHotelName(hotel.HotelCode);
        hotel.Rates = AvailabilityRespository.GetRateInformation(
            hotel.HotelCode, hotel.StayDate, hotel.NumberOfNights);
    }

    private static List<HotelRoomAvailability> GetObjectGraph()
    {
        List<HotelRoomAvailability> result = new List
            {
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONSOHO"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONCOVGDN"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONLEISQR"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONHIGHOL"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONKINGSX"
                    },
                new HotelRoomAvailability
                    {
                        StayDate = new DateTime(2011, 7, 1),
                        NumberOfNights = 3,
                        HotelCode = "LONEUSTON"
                    }
            };

        return result;
    }

    private static void DisplayObjectGraph(
        IEnumerable initialObjectGraph)
    {
        foreach (HotelRoomAvailability availability in initialObjectGraph)
        {
            Console.WriteLine(availability);
            Console.WriteLine(new string('=', 80));
        }
    }
}

Note that not all code is being shown here. There are a number of classes outside the Program class that operate on the data simulated calls to services or other calculations on the data. If you want to see the full example please download the full code sample using the link at the bottom of this post.

Example output

LONSOHO :
Staying on 01/Jul/2011 for 3 nights

================================================================================

LONCOVGDN :
Staying on 01/Jul/2011 for 3 nights

================================================================================

LONLEISQR :
Staying on 01/Jul/2011 for 3 nights

================================================================================

LONHIGHOL :
Staying on 01/Jul/2011 for 3 nights

================================================================================

LONKINGSX :
Staying on 01/Jul/2011 for 3 nights

================================================================================

LONEUSTON :
Staying on 01/Jul/2011 for 3 nights

================================================================================

Populating details of LONSOHO
Populating details of LONCOVGDN
Populating details of LONLEISQR
Populating details of LONHIGHOL
Populating details of LONKINGSX
Populating details of LONEUSTON
LONSOHO : London Soho
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £48.40
02/Jul/2011: £52.80
03/Jul/2011: £44.00
Total Price: £145.20
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £58.40
02/Jul/2011: £62.80
03/Jul/2011: £54.00
Total Price: £175.20
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £83.40
02/Jul/2011: £87.80
03/Jul/2011: £79.00
Total Price: £250.20
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £54.45
02/Jul/2011: £59.40
03/Jul/2011: £49.50
Total Price: £163.35
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £64.45
02/Jul/2011: £69.40
03/Jul/2011: £59.50
Total Price: £193.35
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £89.45
02/Jul/2011: £94.40
03/Jul/2011: £84.50
Total Price: £268.35
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £60.50
02/Jul/2011: £66.00
03/Jul/2011: £55.00
Total Price: £181.50
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £70.50
02/Jul/2011: £76.00
03/Jul/2011: £65.00
Total Price: £211.50
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £95.50
02/Jul/2011: £101.00
03/Jul/2011: £90.00
Total Price: £286.50
----------------------------------------

================================================================================

LONCOVGDN : London Covent Garden
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £59.84
02/Jul/2011: £65.28
03/Jul/2011: £54.40
Total Price: £179.52
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £69.84
02/Jul/2011: £75.28
03/Jul/2011: £64.40
Total Price: £209.52
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £94.84
02/Jul/2011: £100.28
03/Jul/2011: £89.40
Total Price: £284.52
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £67.32
02/Jul/2011: £73.44
03/Jul/2011: £61.20
Total Price: £201.96
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £77.32
02/Jul/2011: £83.44
03/Jul/2011: £71.20
Total Price: £231.96
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £102.32
02/Jul/2011: £108.44
03/Jul/2011: £96.20
Total Price: £306.96
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £74.80
02/Jul/2011: £81.60
03/Jul/2011: £68.00
Total Price: £224.40
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £84.80
02/Jul/2011: £91.60
03/Jul/2011: £78.00
Total Price: £254.40
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £109.80
02/Jul/2011: £116.60
03/Jul/2011: £103.00
Total Price: £329.40
----------------------------------------

================================================================================

LONLEISQR : London Leicester Square
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £61.60
02/Jul/2011: £67.20
03/Jul/2011: £56.00
Total Price: £184.80
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £71.60
02/Jul/2011: £77.20
03/Jul/2011: £66.00
Total Price: £214.80
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £96.60
02/Jul/2011: £102.20
03/Jul/2011: £91.00
Total Price: £289.80
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £69.30
02/Jul/2011: £75.60
03/Jul/2011: £63.00
Total Price: £207.90
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £79.30
02/Jul/2011: £85.60
03/Jul/2011: £73.00
Total Price: £237.90
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £104.30
02/Jul/2011: £110.60
03/Jul/2011: £98.00
Total Price: £312.90
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £77.00
02/Jul/2011: £84.00
03/Jul/2011: £70.00
Total Price: £231.00
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £87.00
02/Jul/2011: £94.00
03/Jul/2011: £80.00
Total Price: £261.00
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £112.00
02/Jul/2011: £119.00
03/Jul/2011: £105.00
Total Price: £336.00
----------------------------------------

================================================================================

LONHIGHOL : London High Holborn
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £59.84
02/Jul/2011: £65.28
03/Jul/2011: £54.40
Total Price: £179.52
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £69.84
02/Jul/2011: £75.28
03/Jul/2011: £64.40
Total Price: £209.52
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £94.84
02/Jul/2011: £100.28
03/Jul/2011: £89.40
Total Price: £284.52
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £67.32
02/Jul/2011: £73.44
03/Jul/2011: £61.20
Total Price: £201.96
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £77.32
02/Jul/2011: £83.44
03/Jul/2011: £71.20
Total Price: £231.96
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £102.32
02/Jul/2011: £108.44
03/Jul/2011: £96.20
Total Price: £306.96
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £74.80
02/Jul/2011: £81.60
03/Jul/2011: £68.00
Total Price: £224.40
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £84.80
02/Jul/2011: £91.60
03/Jul/2011: £78.00
Total Price: £254.40
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £109.80
02/Jul/2011: £116.60
03/Jul/2011: £103.00
Total Price: £329.40
----------------------------------------

================================================================================

LONKINGSX : London Kings Cross
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £61.60
02/Jul/2011: £67.20
03/Jul/2011: £56.00
Total Price: £184.80
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £71.60
02/Jul/2011: £77.20
03/Jul/2011: £66.00
Total Price: £214.80
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £96.60
02/Jul/2011: £102.20
03/Jul/2011: £91.00
Total Price: £289.80
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £69.30
02/Jul/2011: £75.60
03/Jul/2011: £63.00
Total Price: £207.90
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £79.30
02/Jul/2011: £85.60
03/Jul/2011: £73.00
Total Price: £237.90
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £104.30
02/Jul/2011: £110.60
03/Jul/2011: £98.00
Total Price: £312.90
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £77.00
02/Jul/2011: £84.00
03/Jul/2011: £70.00
Total Price: £231.00
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £87.00
02/Jul/2011: £94.00
03/Jul/2011: £80.00
Total Price: £261.00
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £112.00
02/Jul/2011: £119.00
03/Jul/2011: £105.00
Total Price: £336.00
----------------------------------------

================================================================================

LONEUSTON : London Euston
Staying on 01/Jul/2011 for 3 nights
Available Rates:
Rate: One Month Advanced Rate Room Only
01/Jul/2011: £62.48
02/Jul/2011: £68.16
03/Jul/2011: £56.80
Total Price: £187.44
----------------------------------------
Rate: One Month Advanced Rate Bed and Breakfast
01/Jul/2011: £72.48
02/Jul/2011: £78.16
03/Jul/2011: £66.80
Total Price: £217.44
----------------------------------------
Rate: One Month Advanced Rate Dinner, Bed and Breakfast
01/Jul/2011: £97.48
02/Jul/2011: £103.16
03/Jul/2011: £91.80
Total Price: £292.44
----------------------------------------
Rate: Two Week Advances Rate Room Only
01/Jul/2011: £70.29
02/Jul/2011: £76.68
03/Jul/2011: £63.90
Total Price: £210.87
----------------------------------------
Rate: Two Week Advances Rate Bed and Breakfast
01/Jul/2011: £80.29
02/Jul/2011: £86.68
03/Jul/2011: £73.90
Total Price: £240.87
----------------------------------------
Rate: Two Week Advances Rate Dinner, Bed and Breakfast
01/Jul/2011: £105.29
02/Jul/2011: £111.68
03/Jul/2011: £98.90
Total Price: £315.87
----------------------------------------
Rate: Fully Flexible Rate Room Only
01/Jul/2011: £78.10
02/Jul/2011: £85.20
03/Jul/2011: £71.00
Total Price: £234.30
----------------------------------------
Rate: Fully Flexible Rate Bed and Breakfast
01/Jul/2011: £88.10
02/Jul/2011: £95.20
03/Jul/2011: £81.00
Total Price: £264.30
----------------------------------------
Rate: Fully Flexible Rate Dinner, Bed and Breakfast
01/Jul/2011: £113.10
02/Jul/2011: £120.20
03/Jul/2011: £106.00
Total Price: £339.30
----------------------------------------

================================================================================

Program finished

More information