Skip to content

“WaitAll for multiple handles on an STA thread is not supported”

My previous post, Waiting on multiple threads, mentioned Joe Duffy’s approach to synchronising multiple threads using a single WaitHandle. I was in the process of implementing a multi-threaded class library at the time but decided to take a conservative approach and use a WaitHandle for each thread. This is a less scalable solution but wasn’t really an issue as I knew that my class library would never need to use more than 8 threads concurrently.

Initial testing of the library from a COM client revealed a problem that I hadn’t anticipated: the call to the multi-threaded library method resulted in an exception being thrown with this error message:

“WaitAll for multiple handles on an STA thread is not supported”

The problem is that calling WaitAll on the thread WaitHandles from an STA thread blocks the Windows message pump and cannot be allowed otherwise the application would freeze. A quick fix for my class library was to iterate the WaitHandle array that was being passed to WaitAll and call WaitOne on each WaitHandle.

A better long term solution is to use Duffy’s single WaitHandle solution.

Tagged

Waiting on multiple threads

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

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

Virtual Server 2005 R2 and Internet Explorer 8

A couple of weeks ago I praised Microsoft for implementing a change in the .NET 3.5 SP1 framework that allows .NET executable assemblies to be run directly from a network share. I should have known I was tempting fate and sure enough a few days later I was shouting obscenities at the monitor of one of my servers because of a classic Microsoft cock-up.

The server in question is a dedicated VM host running Virtual Server 2005 R2 SP1 under Server 2008. Late last week Windows Update installed Internet Explorer 8. I didn’t notice any problems for a day or two because I was using another PC and Internet Explorer 7 to access the Virtual Server Administration Web Site. But on Wednesday afternoon I was doing some VM maintenance on the server using IE8 and the administration web site and I realised that all was not well. Clicking on the option to merge undo disks resulted in nothing. I tried a few other options like starting up a VM. Nothing. Then I noticed the error icon at the bottom left of the IE8 window and an error message: “Error on page”. 

I tried closing IE8 and restarting it with the same results. A quick search on Google revealed the answer - you need to enable IE8’s Compatibiilty Views feature for it to work with the Virtual Server Administration Web Site. Wonderful - Microsoft have managed to produce a version of Internet Explorer that isn’t even compatible, by default, with its own products.

Tagged

Life outside the Microsoft bubble

I started working for a new company about three weeks ago and it’s been a minor culture shock. Unlike every company I’ve worked for in the past 15 years this one isn’t fundamentally bound to Microsoft tools, technologies, and platforms. That said, the company was interested in my skills and experience in exactly these areas.

A few examples of the differences: the ‘default’ database server for application development is MySQL 5.x instead of SQL Server 2005/2008; SharpDevelop is the standard development IDE; and Thunderbird is used in preference to Outlook.

The most surprising thing to me though is just how capable and mature these products are. MySQL 5.x is simple to install, configure, and use, and the GUI Tools are on a par with SQL Server’s Management Studio. I’m still not a great fan of SharpDevelop (fortunately the company has a few MSDN licences which means I’m still a Visual Studio user) but it’s a very usable and capable tool. Likewise, Thunderbird 2.0 is far from perfect but it’s still a very capable and mature application. 

The company specialises in developing applications in the healthcare sector and is very aware of the sensitivity of its clients’ data. Even anonimised test data must be carefully protected. The company has standardised on TrueCrypt for data encryption and, again, I’ve been very impressed with the maturity of version 6.x. About 6 years ago I checked out most of the ‘encrypted volume’ type products then available and chose to pay for SoftWinter’s Sentry 2020 rather than use TrueCrypt for free. But TrueCrypt has moved on while Sentry 2020 hasn’t. I’m happy with Sentry 2020 and like the fact that the product is stable but TrueCrypt has introduced a few features like hidden volumes and traveller volumes that Sentry 2020, as a commercial product, should probably have implemented some time ago.

The revelation that there is some really good software out there for free has got me checking out possible replacements for at least some of the software that I’ve been taking for granted. So far, I’ve only got as far as looking for replacements for Microsoft OneNote and the application that comes closest is EverNote. EverNote is a good product but it’s made me realise just how good OneNote is. The main problem with OneNote is that people who use it tend to evangelise it and use it for all their notes while those who don’t use it don’t even install it despite it being included in various editions of Microsoft Office. This makes it difficult to exchange OneNote data with other people. I can’t believe it’s a big earner for Microsoft and it’s a shame that they haven’t bundled it with Windows.

EverNote is worth a checking out if you’re looking for an application to store your notes. It’s a different product to OneNote and the two are to some extent complimentary. EverNote can be used as a standalone product but it’s intended to be a client application for EverNote’s web storage. So, you create your notes, synchronise with the EverNote web site, and then your notes are available from any other PC with the EverNote client installed or using the EverNote web site directly. What would be really nice would be OneNote’s document structure and interface, and EverNote’s storage model. ;-)

 

Tagged

.NET 3.5 SP1: Full Trust for .NET executables on network shares

In the early days of .NET it was possible to create a .NET executable, copy it to a network share, and anyone with access to the share could run the executable directly from the share without any security issues. 

It was a very practical solution for applications used within corporate LANs but Microsoft identified a security risk and tightened things up. Network shares were categorized as belonging to the Intranet Zone within the standard .NET security implementation. This meant that you could not run a .NET executable from a network share without altering the local machine’s security configuration to allow this.

Things took a bizarre turn with a bug introduced with Internet Explorer 6 or 7 (I can’t remember which) that incorrectly categorized a network share as belonging to the Internet Zone rather than the Intranet Zone. No matter how much the Intranet Zone security settings were tweaked to allow code execution, the application on the network share would fail with a security exception. One of the possible solutions was to add the network share to the Trusted Sites list in Internet Explorer. This forced the re-categorization of the network share from the Internet Zone to the Intranet Zone. No, I’m not making this up!

Even without that particular bug, changing the security configuration for every machine that you wanted to run the executable on was a nuisance and cancelled out the convenience of using a network share this way.

But, with .NET 3.5 SP1, this issue has come full circle - Microsoft has moved network shares into the default Full Trust security group. So, once again, .NET executables will run directly from a Network share without any changes to the local machine’s default security configuration.

Thanks Microsoft, good call.

Tagged ,

Classic CompuServe

Last month I mentioned that I’d received an email from CompuServe informing me that the Classic service was being shutdown and I’d have to migrate my email address to a new server that CompuServe was setting up.

Yesterday another email arrived to say that I needed to access a page on the CompuServe web site to activate a new account for my old email address.

To cut a long story short - it was one problem after another. A few problems that occurred along the way:

  • The web page wasn’t yet set up to handle the migrations so the instructions in the email didn’t work. I suspect this may have been a time zone issue but plenty of other users had the same experience.
  • Late in the day, UK time, the web page was updated and I was able to login. The instructions were still wrong and the migration process started automatically rather than requiring the user to manually select this option.
  • After the migration process appeared to complete and I was able to access the new email account using CompServe’s web mail interface, I tried to configure my email client to access the account using POP3. The instruction email was unclear about the format of the username that should be used. I tried several permutations and got varying results - most were rejected by the mail server but eventually I realised that the most obvious format of the username was actually failing with a timeout rather than a rejection. This probably meant that the login authentication was working but the mail server wasn’t yet fully configured to actually be used. Possibly this was an account migration issue.
  • I decided to leave it for a few hours at least to see if this was a migraton issue and that the server just needed time for the account to be fully set up. The next day I tried it and it worked perfectly.

There are a lot of frustrated CompuServe Classic users venting their anger in CompuServe’s forums at the way that CompuServe has handled this process. Perhaps not appreciating the irony of his comment, one user’s response was: “This is classic CompuServe!”

Actually, it’s CompuServe Classic… ;-)

For anyone else going through the process, this information might be useful:

  1. Open a web browser and go to http://member.compuserve.com/mailcenter
  2. Login using either your CompuServe ID or your username alias. Whichever you use will become the email address of the migrated email account. So, if you have and use an email alias then login using this otherwise you’ll lose it. The login name should be suffixed with @compuserve.com. Use the password associated with you CompuServe account.
  3. After a few seconds of flashing the page will redirect to an account set up page. Once you’ve completed this and submitted it you’ll be redirected to your new email account at http://webmail.compuserve.com. Note that you’re prompted to enter a new password for the account. I entered my existing CompuServe account password and this was accepted. So, if you’d prefer to keep your existing password, you can.
  4. You can now reconfigure your email client, if you use one, but it won’t work for about 8-12 hours. The server address is pop.csi.com as indicated in the migration email. The username is your new (well, old) email address, i.e. alias-name@compuserve.com and the password that you specified in the account set up in the previous step.

There’s some debate in the CompuServe forums about how and when the new account becomes fully active. CompuServe appear to have said that the migrated account will not receive incoming mail for the Classic email address until a switchover in June. This appears to be incorrect. My experience is that once the new account is accessible via POP3 (several hours after initiating the migration) new mail starts arriving on the new pop3.csi.com server rather than the old Classic POP3 server at pop.compuserve.com.

UPDATE: Another 24 hours on, about 36 hours after the account was migrated, and all my emails from the old email account have now appeared in the new email account.

Tagged ,

Ubuntu 9.04 and cloud computing

Ubuntu 9.04 was released earlier today. Browsing the list of new features this paragraph struck me as potentially very significant:

Ubuntu 9.04 Server Edition makes it easy to experiment with cloud computing. Eucalyptus, an open source technology which is included in Ubuntu as a technology preview, enables you to use your own servers to deploy, experiment and test your own private cloud that matches the Amazon EC2 API. You can dynamically create virtual machines, configure multiple clusters into a single Cloud and even provide an EBS (elastic block storage) equivalent and an S3 compatible storage manager.

Tagged

How long has my computer been idle ?

I have a few applications that periodically perform disk intensive tasks. For example, one checks for new or changed files in the folders that I normally backup. If the number of new or changed files, or the total size of these files, exceeds a threshold then the application starts nagging me to run a backup.

These tasks run with a very low thread priority and any performance impact is usually unnoticable. Nevertheless, it’d be nice to change these tasks so that they run when the computer is not being used. I looked through the .NET framework for methods that might help me determine the current level of activity on the computer but didn’t find anything paritcularly relevant.

Using this code I can now change my tasks to check if the computer is being used before they perform their disk intensive processing.

Then I stumbled across the GetLastInfo function in the Win32 API. This obscure function returns a single value that represents the time that the user last interacted with the computer using the keyboard or mouse. The value is expressed in ticks. This is the number of milliseconds that the Windows has been running since it was started. The .NET Framework Environment class has a static property called TickCount() that returns the current tick value. So, subtracting the value returned by GetLastInfo() from Environment.TickCount gives the number of millseconds since the user last interacted with the computer. For example:

namespace IdleTime
{
    using System;
    using System.Runtime.InteropServices;  

    public static class IdleTime
    {
        [DllImport("user32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        private struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }
 
        public static int Get()
        {
            int idleSeconds = 0;
 
            LASTINPUTINFO LastInputInfo = new LASTINPUTINFO();
            LastInputInfo.cbSize = (uint)Marshal.SizeOf(LastInputInfo);
            LastInputInfo.dwTime = 0;
            
            // If we have a value from the function
            if (GetLastInputInfo(ref LastInputInfo))
            {
                // Get the number of ticks at the point when the last activity was seen
                int lastInputTicks = (int)LastInputInfo.dwTime;
 
                // Number of idle ticks = system uptime ticks - number of ticks at last input
                idleSeconds = (Environment.TickCount - lastInputTicks) / 1000;
            }

            return idleSeconds;
        }
    }
}

Using this code I can now change my tasks to check if the computer is being used before they perform their disk intensive processing.

Tagged

CompuServe Classic R.I.P.

An email from member services landed in my CompuServe classic mail account yesterday:

Dear member,

After many years of service we regret to advise that as of 30 June 2009
CompuServe can no longer offer the internet access we provided to your
address. Subsequently, your CompuServe account will be
closed June 30th 2009.

I signed up with CompuServe in 1994 and although I haven’t used it for the online content for the past six or seven years I still use the email account. The ‘classic’ users such as myself have probably been an inconvenience ever since AOL bought CompuServe but we were still paying a few dollars a month that you’d have thought allowed the service to pay for itself.

CompuServe first offered an online service to personal computer users in 1979. It’s a pity that the 30th anniversary is its death knell rather than a celebration.

Tagged