Monday, August 10, 2009

Clearing event handlers implemented with lambda expressions

One of the niceties included with C# 3.0 is lambda expressions, a concise syntax for implementing anonymous methods. Lambda expressions can be over-used, but they're very handy for certain kinds of things, like defining how asynchronous callbacks should be handled, all within a single method.

Lambda expressions are also very handy for implementing event handlers. For instance, if you've got an AlarmClock class that looks like this:

class AlarmClock 
{
  public event EventHandler<EventArgs> Alarm;
  public void SoundAlarm()
  {
    if (Alarm != null)
    {
        Alarm(this, new EventArgs());
    }
  }
}

You would normally assign and implement an event-handler like this, with a separate defined method:

class Program
{
  public static void Main()
  {
    AlarmClock clock = new AlarmClock();
    clock.Alarm += new EventHandler<EventArgs>(clock_Alarm);
    clock.SoundAlarm();
  }

  static void clock_Alarm(object sender, EventArgs e)
  {
    Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
   }
}

But with lambda expressions, you can do it like this, all in one method:

class Program
{
  public static void Main()
  {
    AlarmClock clock = new AlarmClock();
    clock.Alarm += (s, e) => 
    Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
    clock.SoundAlarm();
  }
}

Most folks would agree that this looks cleaner, and is easier to follow. (At least, once you get the hang of lambda expressions, which admittedly have a rather odd syntax.)

The one time this doesn't work is when you need to be able to clear event handlers as well as assign them. The way that you normally do this is so:

public static void Main()
{
  AlarmClock clock = new AlarmClock();
  clock.Alarm += new EventHandler<EventArgs>(clock_Alarm);
  clock.SoundAlarm();
  clock.Alarm -= new EventHandler<EventArgs>(clock_Alarm);
}

But you can't do that with the lambda expression I used above, because you don't have any way to identify the lambda expression that you want to remove. I've seen a variety of folks asking questions about how to clear event handlers implemented as lambda expressions for this very reason.

It turns out that there are (at least) two ways to do it.

If you've got access to the source code for the class in question, you can write a public ClearEventHandlers() method that works like so:

class AlarmClock
{
    public event EventHandler<EventArgs> Alarm;
    public void SoundAlarm()
    {
        if (Alarm != null)
        {
            Alarm(this, new EventArgs());
        }
    }
    public void ClearEventHandlers()
    {
        Alarm = null;
    }
}

But if you need more granularity, or don't have access to the source, you can assign the lambda expression to a variable (e.g., "handleAlarm") before you assign it as an event-handler, like so:

public static void Main()
{
    AlarmClock clock = new AlarmClock();
    EventHandler<EventArgs> handleAlarm = null;
    handleAlarm = (s, e) =>
    {
        clock.Alarm -= handleAlarm;
        Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
    };
    clock.Alarm += handleAlarm;
    clock.SoundAlarm();
}

Note that you need to assign the handleAlarm variable to null first, because otherwise the compiler complains about the first line of the lambda expression: it thinks that you're trying to muck about with an uninitialized variable. This is only sort of true, but to work around it, just assign the variable to null when you declare it.

The syntax for #2 is a bit unwieldy, but it can let you do things that would be difficult or complicated if you had to use a second method. For instance, within lambda expressions you can use local variables declared at the level of the containing function:

public static void Main()
{
    AlarmClock clock = new AlarmClock();
    EventHandler<EventArgs> handleAlarm = null;
    ManualResetEvent resetEvent = new ManualResetEvent(false);
    bool alarmSounded = false;
    handleAlarm = (s, e) =>
    {
        clock.Alarm -= handleAlarm;
        Console.WriteLine("The alarm went off at {0}.", DateTime.Now);
        alarmSounded = true;
        resetEvent.Set();
    };
    clock.Alarm += handleAlarm;
    clock.SoundAlarm();
    resetEvent.WaitOne(5000);
    if (!alarmSounded)
    {
        Console.WriteLine("The alarm didn't sound within the timeout period.");
    }
}

To duplicate this without lambda expressions, you'd have to declare the resetEvent and alarmSounded variables at the class level, which isn't nearly as clean, and could lead to some odd bugs if other methods were trying to use those same variables simultaneously.

Windows 7: Not Terribly Impressed

Windows Vista was never as bad as its reputation; and Windows 7 is not as good as everyone claims. It's not bad, but it still needs some work. And I dislike some of the design decisions.

Here are a few snippets from my own experience:

  • Something is wrong with the graphics drivers or graphics subsystem. Applications that worked fine under Vista keep "flickering" in Windows 7. And my Chrome browser keeps displaying a weird sort of static when it opens a new page, sometimes just for a quarter-second, sometimes permanently. Perhaps this is just a case of a bad video driver (I'm running an NVIDA GeForce 8800 GT), but I've installed the latest Windows 7-optimized driver, and it's still happening.
  • I've had two different blue-screens in my 48 hours of running Windows 7 RTM. Not a reassuring way to start a new relationship.

The computer has rebooted from a bugcheck. The bugcheck was: 0x0000001a (0x00001236, 0x878be008, 0x878be08c, 0x00070054). A dump was saved in: C:\Windows\MEMORY.DMP. Report Id: 081009-37970-01.

The computer has rebooted from a bugcheck. The bugcheck was: 0x0000008e (0xc0000005, 0x8c28b885, 0xb062b750, 0x00000000). A dump was saved in: C:\Windows\MEMORY.DMP. Report Id: 081009-30061-01.

  • If you turn off UAC (you pretty much have to, unless you're the sort of person who shops here), the UI gives you the impression that it's taken effect right away – and some parts of it have. But you have to restart your machine to actually be able to launch everything as an Administrator. This is no different from Vista, except that the UI is more honest in Vista, and tells you that you need to reboot.
  • I dislike the new metaphor for "pinning" applications to the taskbar. Among other things, it means that if I have multiple instances of an application open, I have to click twice to switch to the right one, rather than just once. It's also much more difficult and confusing to tell at a glance if something is open. I don't get why MS thought that clicking twice is better than clicking once. Luckily, you can turn this behavior off; but it's still an odd default.
  • I don't get the new file manager. It lists very prominently a whole bunch of shortcuts that I've never found useful, and hides the thing I actually do want to use, a direct tree view into my file system. On top of that, it doesn't synchronize the tree view with where I've navigated to in the file system. So the tree view can be sitting at C:\, long after I've navigated to, say, C:\source\slidelinc\branches\98a_SlideLincClient_ken. This last is a behavior that you can change if you know where to look, but it's a rather weird and unpleasant default.

Again, none of these things are killers, and maybe some people will like the new UI and its associated defaults. On the whole, Windows 7 is OK, though not terribly impressive. It feels to me like a not-very-ambitious bug-fix to Vista. I'll run it. But I continue to wish that MS could be more successful at their core operating system business.

Monday, July 27, 2009

Why WPF databinding is an awful technology

[Edited 10/23/09: I wrote this blog post when I was in a pissy mood, because I'd just wasted a day trying to get some WPF databindings to work. I still agree with my critiques of WPF/Silverlight databinding, and I think that MS really needs to rethink some aspects of their databinding implementation, especially their failure to implement a strongly typed DataContext. Still, if I were to write this post now, I'd be less inflammatory, especially in my opening paragraphs. Just to put it in perspective. But on to the original post . . . ]

I hate WPF databindings. Let me say that again. I hate WPF databindings. Of all the technologies to come out of Microsoft over the last five years, WPF (and Silverlight) databindings are easily the most awkward to configure, the least intuitive to use, the hardest to troubleshoot, and the easiest to get wrong. XAML itself is an ugly, verbose language, but once you get used to it, it's at least possible to get the UI pieces right with a little bit of troubleshooting. But setting up bindings in XAML is a different world altogether.

Microsoft claims, with some justice, that XAML/WPF/Silverlight provide for a very clean separation of concerns between the UI and the business logic, and this is true. But the reason to have a clean separation of concerns is to make things easier for the developer and the designer. And any benefits that may accrue from this theoretical achievement are entirely wiped out by Microsoft's piss-poor, half-assed, god-awful implementation. I've spent many painful hours troubleshooting WCF bindings, I've pored over bizarre Linq-to-Entity query side-effects until I couldn't see straight. But my time has never been so fruitlessly spent as trying to get my databindings right in XAML.

I could give you an example from nearly every single WPF form I've ever tried to design, but let's just go with this one, taken straight from this MSDN article. Create a simple form that looks like this:

<Window x:Class="WpfDatabindingDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <XmlDataProvider x:Key="MoreColors" XPath="/colors">
            <x:XData>
                <colors >
                    <color name="pink"/>
                    <color name="white"/>
                    <color name="black"/>
                    <color name="cyan"/>
                    <color name="gray"/>
                    <color name="magenta"/>
                </colors>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
    <Grid>
        <ListBox x:Name="lbColor" Width="248" Height="200"
            IsSynchronizedWithCurrentItem="True"
            ItemsSource="{Binding Source={StaticResource MoreColors},
            XPath=color/@name}">
        </ListBox>
    </Grid>
</
Window>


And note that in the Visual Studio form designer, you see the data, as you'd expect:



But then try to run the application, and you'll note that the data doesn't show up.



There's no explanation as to why the data doesn't show up. There's no error in the Visual Studio debug output window. There's no error anywhere. The data simply isn't there. And note that this WPF binding error is taken straight from Microsoft's own documentation! But the biggest problem isn't that Microsoft's own proof-of-concept, easy-as-pie, this-is-how-you-learn-this sample code doesn't work: it's that your program fails silently, without an error, and without any debugging information.

If you want to know why it doesn't work, you have to add a short but ugly little piece of XAML to turn on extended diagnostics. (By "ugly" I mean, "You'll never remember what to type unless either (a) you Google it and then cut-and-paste the example into your code; or (b) this is the 57th time you've had to do this." I'm quickly approaching (b).)

First you have to register the diagnostics namespace:

<Window x:Class="WpfDatabindingDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
Title="Window1" Height="300" Width="300">

And then you have to turn the trace level on to "High".

<ListBox x:Name="lbColor" Width="248" Height="200"
    IsSynchronizedWithCurrentItem="True"
    ItemsSource="{Binding Source={StaticResource MoreColors},
    XPath=color/@name,
    diagnostics:PresentationTraceSources.TraceLevel=High}">

And then when you run your app, you finally see this error in the Visual Studio output window:

System.Windows.Data Error: 47 : XmlDataProvider has inline XML that does not explicitly set its XmlNamespace (xmlns="").

Another hour or so of poking around on Google, and you realize that you have to add the blank namespace to your XML data, like so:

<XmlDataProvider x:Key="MoreColors" XPath="/colors">
    <x:XData>
        <colors xmlns="" >
            <color name="pink"/>
            <color name="white"/>
            <color name="black"/>
            <color name="cyan"/>
            <color name="gray"/>
            <color name="magenta"/>
        </colors>
    </x:XData>
</XmlDataProvider>

And after only two or three hours of troubleshooting (if you're lucky), you've fixed your problem. But my point is that this isn't something that you should have had to troubleshoot. This is something that either (a) should have worked out of the box, as the MS sample code led you to believe, or (b) should have thrown a simple and explanatory runtime error, or (c) even better, should have been caught at compile-time, since everything that the compiler needed to know to realize that this wouldn't work is already there in the source code. Any of those three options would have been fine. But it's simply not acceptable to fail silently, without even a hint about what's going wrong.

This is just one example, of course.  I could produce plenty of others, but then this post would get even more boring and repetitive than it is.

The fundamental problem with Microsoft's data binding implementation is that it's a significant step backwards in terms of computer language theory. Folks have known for years that strongly typed languages help you write better code. It's better to catch an error when you're writing your code than to catch it at compile-time;  it's better to catch an error when you compile your code than to catch it at run-time; if the compile doesn't catch it, at least your automated tests should be able to; and of course it's better to throw an error (even at runtime) than to fail silently. But the way that MS has implemented bindings, there's no way to catch errors at any of these steps: neither when you're designing your form, nor when you're compiling your app, nor when you're running your tests, and most inexplicably, not even when you're running your application. The minute you type "{Binding…}", you're working without a net.

For instance, MS could have implemented the XmlDataProvider in such a way as to allow (or even require) you to specify an XSD file as a parameter.  If they had, not only could you get Intellisense when typing in your bindings, but you could also receive a helpful compiler error if it sees, say, that you've bound your ListBox ItemsSource to an element or an attribute that doesn't exist. Similarly, if you're using an object data source, you should be allowed to declare the type up-front, and then only bind to properties available in that type. And if the binding fails at run-time, e.g., the object isn't available, or doesn't have the properties available that you're trying to access, you should get exactly the same sort of error that you'd get in C# if you tried to access a non-existent property on a class from a third-party DLL. In other words, it should not only fail (which it does now), but it should tell you why it's failing, and it should tell you this before you ever run your application.

In other words, MS should have made the DataContext property strongly typed. It would allow the Visual Studio tools to do in milliseconds what you can only do now through hours of futile Googling and days of pointless troubleshooting. Microsoft decided that they wanted the extra flexibility that comes from not having any type safety, and I agree that there are scenarios where this flexibility is helpful. But there's a reason nobody writes enterprise applications in VBScript: type safety is orders of magnitude more important than flexibility when working with complex systems. And I would willingly, in a heartbeat, give up some extra flexibility, in exchange for knowing immediately why my bindings won't work, instead of waiting until I run the app to find out that they don't work and not having a clue as to why.

Undoubtedly this would require a pretty significant rethinking of how data binding works with XAML. Neither WPF nor Silverlight would look the same when they were done. But that may be exactly my point. MS had the chance to get WPF right; and they missed a huge opportunity. And until they fix this, their databinding implementation will remain a significant drag on the adoption of WPF and Silverlight. Without strong typing, WPF databinding is just too difficult to use.

Monday, July 6, 2009

No Comment Necessary

I got this dialog box today:

I guess it's sort of self-explanatory.

Friday, May 22, 2009

Pair Programming

I've recently found myself a new late-night programming buddy.

He generally hangs out in a chair next to my desk, a vantage point which allows him to make frequent comments on the quality of my work.

His name is Brendan Javier Michael Smith, and he joined our family last Wednesday. He's about as cute as they come, even if he's not (yet) much of a coder.

See here and here for more pictures.

Friday, May 8, 2009

Asynchronous WCF Methods in Silverlight

I'm not sure whether I should love or hate a language that lets me write code like this:

   private void InitData()
    {
        RoomServiceClient rc = new RoomServiceClient(wsBinding, roomServiceEndpoint);
        rc.GetUserCompleted +=
            delegate(object sender, GetUserCompletedEventArgs e)
            {
                user = e.Result;
                rc.JoinRoomAsync(App.OwnerUserID, App.RoomName, App.UserID);
            };
        rc.JoinRoomCompleted +=
            delegate(object sender, AsyncCompletedEventArgs e)
            {
                rc.GetRoomAsync(App.OwnerUserID, App.RoomName);
            };
        rc.GetRoomCompleted += 
            delegate(object sender, GetRoomCompletedEventArgs e)
            {
                UpdateLocalState(e.Result);
            };
        rc.GetUserAsync(App.UserID);
    }

Sunday, April 26, 2009

Blinkx Acquired 100% of Zango’s Assets

I've seen a number of online articles (here and here, for instance), which say that Blinkx has acquired only "ten percent" of Zango's assets. This wouldn't be the first time that a corporate spokesman has honestly misunderstood the actual state of affairs, or has been badly misunderstood by the reporters to whom he was speaking. So I don't want to jump to any conclusions. But I should be clear that Blinkx acquired fully 100% of Zango's assets. As a Zango shareholder, I now own a percentage of precisely nothing, and the banks have nothing left of Zango's which they can sell. Blinkx owns it all.

In addition, there have been postings on various forums which indicate that Zango's assets were purchased by a company called "Pinball". In this case, not being a Blinkx insider, I'm not entirely sure of the relationship between Pinball and Blinkx: Pinball may be a subsidiary of Blinkx, a DBA, or something else. But Zango's assets were acquired by Blinkx, not some hitherto unknown company, so it's clear that the corporate "thing" that is Pinball is not appreciably different from the corporate "thing" that is Blinkx.

I should note that Zango itself had a variety of subsidiaries and brands, such as Hotbar, SmartShopper, Platrium, and so forth, so there's nothing necessarily nefarious in Blinkx doing this – unless, of course, they're trying to obfuscate or deny their involvement. But that would sure seem like a foolish thing for a public company to do.