I’m currently implementing an interface that needs to communicate with several servers each time its methods are called. To reduce the elapsed time required the calls to each server are made concurrently using a thread per server. So what’s the best way to wait for all the threads to complete ?
If you search the internet you’ll probably find code examples based on using a semaphore for each thread. When the thread is started the Semaphore’s count is set to 1 (a non-signalled state) and when the thread completes the count is set to 0 which puts the Semaphore into the signalled state. The Semaphore’s static WaitAll() method is used to wait for all the Semaphores to enter the signalled state.
If you know anything about threading then you’ll probably know that while you can use a semaphore in this way, a ManualResetEvent is a better match for what is required here. Each thread uses a ManualResetEvent which is initialised in its non-signalled state by passing false to its constructor. When the thread completes it puts the ManualResetEvent into the signalled state by calling its Set() method. As in the previous example, the WaitAll() static method of the ManualResetEvent class is used to wait for all the threads to complete.
The problem with both these approaches is that creating lots of WaitHandles (the object that underlies the implementation of Semaphores and ManualResetEvents) has a fairly high overhead. This might not be worth worrying about for a few threads but if you want a scalable solution then using a WaitHandle per thread isn’t a good idea.
Joe Duffy presents an elegant solution to this problem on page 368 of his recently published Concurrent Programming on Windows. The code uses a single ManualResetEvent that is initialised in its non-signalled state and a thread safe count of the number of active threads is maintained using the Interlocked object:
activeThreadCount = 0;
manualResetEvent = new ManualResetEvent(false);
foreach (string server in urls)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWork);
worker.RunWorkerAsync();
Interlocked.Increment(ref activeThreadCount);
}
When each thread completes it reduces the active thread count by 1 and if the counter has reached 0 then the ManualResetEvent is signalled by calling its Set() method:
if (Interlocked.Decrement(ref activeThreadCount) == 0)
{
manualResetEvent.Set();
}
Now the code that is waiting for the threads to complete only needs to call the ManualResetEvent’s WaitOne() instance method:
manualResetEvent.WaitOne();
Tagged Development
Moore’s law: Laptops
Over the past nine years I’ve bought several laptops from Dell. It’s interesting to look at how the specifications and prices have changed.
Moore’s Law makes the observation that, historically, computing power has doubled roughly every two years. Although Moore didn’t specifically state this, it’s generally considered that this doubling in computing power is delivered to the consumer for the same cost. So, roughly every two years we get twice the computing power for the same price. As manufacturers have sought to lower the entry cost of a computer they’ve flipped this around to offer the same computing power for half the price every two years.
As an example, here’s three of the laptops that I’ve purchased:
2000: Dell Inspiron 5000e / Intel Pentium 4 733Mhz / 256Mb RAM / 30Gb disk - £2200
2005: Dell Inspiron 9200 / Intel Pentium 4 1.6Ghz / 1Gb RAM / 60Gb disk - £1500
2009: Dell Vostro 1710 / Intel Core Duo 2.6Ghz / 4Gb RAM / 320Gb disk - £750
The correlation to Moore’s Law is striking. These three laptops were bought at intervals of approximately 4 years and each cost roughly half what the previous laptop cost and delivered twice the computing power, four times the memory, and at least twice the disk capacity.
The reduction in cost is particularly impressive when you consider the additional features that we take for granted on a modern laptop - high resolution screen, NIC, WiFi, memory card reader, etc. The Dell Inspiron 5000e was a premium laptop when purchased in 2000 but had no built-in network connectivity. That seems astonishing in today’s online world. A PCMCIA network adapter cost another £120. I replaced this in 2003 with a IEEE 802.11 B WiFi card that cost £40. A year later this was replaced with a IEEE 802.11 G card costing £20.
However, what Moore’s Law doesn’t tell us is exactly how manufacturers achieve the reduction in prices. The latest laptop is probably the least well built of the three and the keyboard is amongst the worst I’ve ever used. Perhaps this is a slightly unfair comparison as the Vostro is Dell’s newer range targeting the home and low-end business market but it must reflect, to some extent, the fact that it’s just not possible to build a laptop to the same quaility level when you halve the retail cost every couple of years.
Tagged Comment