How is C# threading like peeling potatoes?

I’ve been working on the Threading lessons for the C#, ASP.NET and Visual Studio Expert Skills book, and an interesting analogy struck me.

I have a sack of potatoes that need to be peeled as quickly as possible. I also have two chefs, Jo and Bill, who are in kitchens on opposite sides of a building.

In the first scenario, I deliver the potatoes to Jo and Bill one at a time, running backwards and forwards from the sack. It takes so long for me to carry each potato to the chefs that it would actually be faster to peel them myself.

This is the same when working with C# threads. Using two threads to accomplish a lot of small tasks is actually slower than doing all of the tasks using a single thread because of the overhead that’s added by managing the threads.

This code uses the “single potato” approach to check prime numbers up to MaximumValue:

while (CurrentValue < MaximumValue)
{
    if (!FirstThread.IsAlive)
    {
        FirstThread = CreateThread();
        FirstThread.Start(CurrentValue);
        CurrentValue++;
    }
    if (!SecondThread.IsAlive)
    {
        SecondThread = CreateThread();
        SecondThread.Start(CurrentValue);
        CurrentValue++;
    }
    Thread.Sleep(1000);
}

This code gives each prime number to the two threads individually. The prime numbers are the ‘potatoes’ in this instance. Because there’s so much overhead starting and stopping the threads, this code is actually much slower than it would be if it didn’t use any threading code at all!

So what’s the solution to the potato problem?  Well of course, it doesn’t make any sense to carry the potatoes one at a time. It would be much more logical to give half of the potatoes to Bill and the other half to Jo. That way they can do their jobs and there’s no time wasted running backwards and forward from the potato sack.

In C# terms, that means our solution is to divide up the prime numbers between our two threads and have each thread process them all in one go instead of starting a new thread for each number.

Here’s how the code looks with the prime numbers divided up between the two threads.

Thread Thread1 =
new Thread(new ParameterizedThreadStart(CalculatePrimes));
Thread1.Start(new int[]{2,StartingPointForThread2-1});
Thread Thread2 =
new Thread(new ParameterizedThreadStart(CalculatePrimes));
Thread2.Start(new int[] { StartingPointForThread2, MaximumValue });

while (Thread1.IsAlive || Thread2.IsAlive)
{
    Thread.Sleep(1000);
}

In this code, the two threads only start once and don’t need to restart for each prime number. This implementation is much faster than working with a single thread (or peeling all of the potatoes yourself!).

There’s a lot more about threading in the Expert Skills book, including using the ThreadPool class to manage threads more easily. ‘Learn ASP.NET 4.0, C# and Visual Studio Expert Skills with The Smart Method’ will be available for purchase around June 2012.

Leave a Reply

Your email address will not be published.

Blue Captcha Image
Refresh

*