January 2007 - Posts

Well, Vista has been officially released, but guess what? The nVidia drivers I thought wouldn't have been released haven't. I hate being right. In fact, happy days, nVidia have deigned to release a new Beta driver. Well done nVidia! The new OS has finally been released after almost a 5 year delay, and you've managed to figure out a beta driver! I mean everyone was going on about Longhaul, but the reality is that the delays Microsoft had was nothing compared to the sheer incompetance of the hardware manufacturers. Oh, yeah Creative can be welcomed to the "we can't write a driver given 5 years" club too.

So, here I am stuck with a disastrously buggy OS, and frankly I can't tell if it's Microsoft's fault or not, but unlike the drivers the OS isn't in Beta, so I guess it's not. Until further notice I hereby place all blame for poor Vista reviews on the utterly moronic planning of companies such as Creative and nVidia. Once they actually release official drivers we'll see if that stance can be revised, but I'm not holding my breath. I'd guess that stable drivers are still some months away.

What I still don't get is why Microsoft isn't raising all kinds of hell about this.
 

Update 3 Feb 2007

Well, it seems that some nVidia owners are starting a class action lawsuit against nVidia. Good for them! I wish them luck. A friend of mine was conned into buying the 8800, which for quite some time was effectively a paperweight. I have my doubts as to what damage could be claimed from not been able to play games though ;-D However, they do seem to be collecting photos claiming that nVidia's hardware is Vista-ready, which it is clearly not. Nonetheless it must be said that at least there is some traction from nVidia's side, they released new drivers recently, albeit still as buggy as hell, with over 27 features not fully implemented, and of course still in Beta. But as pathetic and useless as that may be, at least they've actually released something. The same cannot be said for Creative. The latest set of drivers for my Audigy is dated 12th Jan 2007.

Unbelievably, much as I thought it would be impossible, the latest nVidia drivers (100.59) are actually significantly more buggy than the previous drivers (97.46). In fact, I have had over 14 complete system lockups today alone, all from the sheer difficulty of rendering my screen saver. I cannot, under any circumstances express my sheer hatred of nVidia at this point without swearing like a trooper. All I can say is they and Creative are now on my "never buy from these guys again" list.

In fact nVidia have been caught censoring the righteous anger of their customers (one of the reasons for the class action suit), and have posted some guidelines for posting in future, I especially enjoy these ones:

  • "Post [that] the [hardware/software] [does] not work", hmm let's see, my computer does a complete lockup when attempting to render my screensaver, such that I must reboot. This replaces the previous buggy behaviour with worse symptoms, the only thing that has changed is the driver, so I guess it must have nothing to do with nVidia's hardware or software, right?
  • "Ask for direct response from nVidia". Wow! That one's a doozy. Let me get this straight, customers will be banned and censored for daring to ask where the drivers for their hardware are? If we ask about timeframes, why the drivers are so buggy, why it took 5 years to deliver beta drivers or any other pertinent questions, then our posts will be deleted?

So, the end result? Well, Vista is coming off my machine, and I will not be reinstalling it until SP1 is out, if then. This goes down as my worst OS upgrade in history, and I'm including Windows ME in that equation, so you can figure how bad it has been. If I just wanted a pretty OS I'd get a Mac. It may not be able to play decent games, or run any of my tools, but frankly neither can the very expensive paperweight sitting on my desk.

At least with a Mac I might be able to watch my screensaver...

Okay, so for once I wasn't an early adopter, but I tend to be a bit conservative with OS upgrades, especially one as fraught as Vista has been. In any case, I've upgraded only my home machine, which is basically a games machine *** file server, my main development box, my laptop, is remaining Vista free. So, I've been using Vista for the whole weekend so what do I think? Well, it appears to be one of the buggiest operating systems I've ever used. It's blue screened once, required reboots 9 times (not counting software installations), had screen artifacts jagging crazily about the screen, is incapable of playing a video file or DVD for more than a few minutes, and is constantly excercising the CPU, even when there shouldn't be any activity. But it is pretty.

Yep, the UI is certainly very slick. The way that the icon of an AVI contains a still frame from the movie, and then the folder's icon it's in contains a couple of frames from of the movies in the folder. I like the new address bar very much, and the UAC doesn't appear to be as irritating as I had feared. As a friend of mine said, suddenly XP looks very cartoony in comparison. Also, it's problem resolution is brilliant compared to the moron one installed with XP ("We are still investigating this problem, for the last 4 years"), and is actually helpful, even going so far as identifying a PCI card without drivers and downloading and installing them while I was still busy looking for the website. I had just arrived on the driver download page, and suddenly the card started working. I must say I was impressed.

But... all that is nothing against the massive stability problems plaguing my computer. Frankly it looks like the blame can be laid on nVidia. They (and Creative Labs) appear to have totally fluffed their Vista drivers. Fair enough, they are beta drivers and maybe I'm speaking too soon, maybe suddenly they'll have fully functional stable drivers by Tuesday, but frankly I doubt it. They seem convinced that they will do the seemingly impossible deed of completing the functionality of their drivers (yes, they're apparently not yet feature complete, at least in nVidia's case), as well as stabilizing them in a couple of days. To me it looks unlikely. I wonder how unhappy someone would be who goes out buys Vista, installs it, and his computer stops working. I don't think your average guy in the street would have any doubts that it's Microsoft's fault. In a sense he'd be right. If the drivers are this poor, Microsoft should have been raising a holy stink about it, but they haven't as far as I've seen.

The end result is that we're just a couple of days from Vista release with all the hardware manufacturers promising drivers ready for release, but all the beta drivers actually out being horrifically far from release quality. In any case, wouldn't it have made sense to ship the drivers with Vista? Now, even if you've got quite old hardware (like my video card), the latest Vista release won't support it out the box, and you'll have to download what will quite possibly be a buggy driver.

Oh yeah, one cool feature in Vista, the Reliability Monitor. The only trouble is that of 5 driver crashes, 3 forced restarts, 6 non-forced but neccesary restarts, 4 major system slowdowns and about 5 application shutdowns plus a blue screen, it's picked up: 1 application shutdown and 1 driver crash. So, it seems the Reliability Monitor isn't too reliable itself.

Conclusion

If these driver issues get sorted out, Vista should be fantastic. They're not too much of a hardship for me, since it's basically a spare machine, so I'm not getting worked up about it. I hope that in future Microsoft will insist on drivers being ready way before release date. I mean, for goodness sakes with all the delays in the Vista project the hardware manufacturers have had about 5 years to get ready for this.

I don't know how many of my South African readers have heard about it, but it appears that our darling electricity monopoly, Eskom, has so ballsed things up that we will have countrywide rolling blackouts. They're calling it "load-shedding", but that's just semantics. It appears that once again they've managed to stuff up the nuclear reactor at Koeberg. How many times is this in the last year now? 3 times? Are their staff so utterly incompetant that they allow a nuclear reactor to fail 3 times in one year? All I can say, is I'm grateful I live up in Johannesburg, because at this rate there's an outside chance that large parts of the Western Cape may soon resemble Pripyat in the Ukraine, you know the now abandoned town near Chernobyl...

I mean it's bad enough that they effectively took a bet about ten years ago that the economy was going to tank, and therefore there was no need to build new power stations. Whoops! Unheard of growth rates later, and we're faced with a slight problem! Of course they could have started building new stations, or un-mothballing old ones as soon as they saw the economy growing, say about 7 years ago, but they obviously decided to leave it to a little past the last minute. I hear they're now building a couple of new plants near the Western Cape. That's good news. Do they perhaps think that maybe, just maybe, the province which supplies the heart of South Africa's economy could get a couple too? Oh wait, the Western Cape black outs were last year, so I guess they'll start building the power stations for Gauteng next year sometime, which means that they should be up and running in time for the 2018 World Cup. Oh, crap, was that 2010?

With the whole BeginInvoke, EndInvoke thing for delegates, I had always thought that you should call EndInvoke, but you didn't have to. Turns out I was wrong. IanG discusses this here.

The Windows Forms UI is not thread-safe, and most calls to WinForms components must be made from the thread that created them. Basically, every WinForms application has a UI thread and zero or more background threads. Control access must be via the UI thread. All well and good, but how do you accomplish this when dealing with background threads? As I see it, there's two main approaches.

Caller-driven marshalling

In this model, the code that is calling the component is responsible for any marshalling. A lot of library code is like this, pretty much everything using the BeginX...EndX pattern, such as System.IO.Stream. So, you can make your call to BeginRead, and pass in an AsyncCallback for the Stream to call when the read has completed. However, it's now up to you to take responsibility for marshalling that information back to your UI thread. The pattern I use in this situation is to call a method which will invoke itself to the UI thread:

private delegate void CompletionHandler(object result);

 

private void CompletionAction(object result)

{

    if (!InvokeRequired)

    {

        // Do work

    }

    else

    {

        // We're in a background thread, so we call ourselves

        // whilst marshalling to the UI thread

        Invoke(new CompletionHandler(CompletionAction), result);

    }

}

As you can see, this method can be called from UI and background threads with impunity and will automatically marshal itself to the UI thread.

A downside of caller driven synchronization is that it requires a level of understanding about threads that the people using the code may not have, which is why we come to:

Callee-driven marshalling

In this model the callee is responsible for marshalling the work back to the UI thread. If it's a control, this is easy, and you can just use the marshalling pattern I used above. If not, things become quite a bit more difficult. I'm a masochist, and tend to only use controls when I must have a UI. This, needless to say, makes my life more difficult. In .NET 2.0 life becomes a lot easier with the advent of the BackgroundWorker component. However, being a masochist, as mentioned before, I personally consider the BackgroundWorker bloated for anything other than the UI, so when I'm writing a threaded component, I instead use AsyncOperation which is actually how the BackgroundWorker component internally does what it does.

An AsyncOperation is created by a call to AsyncOperationManager.CreateOperation, and then used by calling Post and PostOperationCompleted. These methods marshal the call to the thread context in which CreateOperation was called. Note, not the thread, the context. So, for a Console application, where there is no thread affinity, these methods do no marshalling whatsoever, and I believe they also do nothing for ASP.NET. For WPF, again they should do nothing, but for WinForms they will marshal between Background and UI. Very cunning if you think about it, this is one pattern you can use to ensure that if there is thread-affinity you adhere to it, and if there isn't you don't suffer a big peformance hit, basically it just adds a virtual method call.

So, the pattern I use to take advantage of this is a bit more complex, but not difficult: 

public class MyComponent : Component

{

 

    private AsyncOperation _asyncOperation;

 

    public void Start(string path)

    {

        _asyncOperation = AsyncOperationManager.CreateOperation(null);

 

        // Kick off async operation, which will call FireAction

        // when done

    }

 

    private void FireAction(string result)

    {

        // We're in the background thread, so now we'll marshal back

        // to the main thread context

        _asyncOperation.Post(new SendOrPostCallback(AsyncActionFired), result);

    }

 

    private void AsyncActionFired(object result)

    {

        // We're on the UI thread, but let's call a typed variant.

        // Note that I make this method private since it is not

        // type-safe, we don't want to expose what in theory could

        // be corrupt parameters to inheritors

        OnActionFired((string)result);

    }

 

    protected virtual void OnActionFired(string result)

    {

        // We're on the UI thread so fire the event or whatever

        // Note that this method does NOT have to be private, since

        // it's type-safe and on the right thread, you can allow

        // inheritors access to it

    }

 

}

For clarity I've left out OperationCompleted/PostOperationCompleted, but they're basically just called when you're finished whatever you were doing.

Wrapping up

So, on a few occasions, I've provided the entire gamut. I've supplied a class which handles threading in a caller-driven manner, a component which uses that class and exposes it's threading in a callee-driven manner, and a control which uses the component to fetch the information it will display. Overkill? Perhaps, but I can be damn sure that my code will support all levels of user: those using the code directly without threading, those just using the control or component and getting the threading for free, and those handling the marshalling themselves. The other nice thing is that such an approach also fits all levels of UI customisation, and I can support people who want to roll their own UI as well as people who just want to use my default UI.