Wintellect  

I fixed a bug in my Silverlight Enigma simulator that prevented it from working properly on many machines with non-U.S. regional settings. And in so doing, I learned a lesson about XamlReader.Load that I'm going to try to take to heart in the future.

The Enigma simulator uses XamlReader.Load to create the rectangles used to depict cables when you connect plugs on the plugboard. Previously, the call to XamlReader.Load looked like this:

Rectangle rect = (Rectangle)XamlReader.Load(String.Format(template, length, x, y, angle));

Unfortunately, this call to XamlReader.Load throws an exception if the PC on which it is executed is configured with regional settings (for example, French [fr-FR]) that uses commas rather than periods to represent decimal points. In other words, some regional settings require "1.0" to be entered as "1,0." The solution is to pass a NumberFormatInfo object in XamlReader.Load's first parameter that expresses this setting. And you can get a NumberFormatInfo object from Thread.CurrentThread.CurrentUICulture.NumberFormat, which Silverlight automatically initializes from the local machine's regional settings. Therefore, the correct way to call XamlReader.Load is as follows:

Rectangle rect = (Rectangle)XamlReader.Load(String.Format(Thread.CurrentThread.CurrentUICulture.NumberFormat, template, length, x, y, angle));

The online Enigma simulator has been refreshed with this code, and you can download the updated source code here.

International travel can be a joy or it can be a pain. As I pack my bags to return to Hyderabad, India this afternoon, I’ve tried to pack my carry-ons smartly but lightly. My carry-on items include:

  • Spare pair of short pants (it’s hot in Hyderabad, even this time of year) and a T-shirt in case my luggage is delayed for days as it was the last time I traveled to Hyderabad, or in case I get orange juice dumped on me again during the flight.
  • Toothbrush, toothpaste, and deodorant—handy for refreshing yourself near the end of a long flight, and even handier if your luggage doesn’t make it.
  • Plenty of reading material: three novels, the last three issues of Jet Power magazine (which I have judiciously avoided reading to save them for the trip), and the latest issues of Model Airplane News, Fly RC, Flight Journal, and Aviation History.
  • Sandwich-size bag of gorp: my own concoction of M&Ms, raisins, and cashew nuts.
  • Enough rupees to get me to my hotel even if I don’t have the opportunity to change money. And some extra US dollars in case I need cash and can’t find a cash machine.
  • Laptop computer, charger, spare charger, and travel mouse. Nothing makes time on an airplane fly by like immersing yourself in work—especially if that work involves writing code.
  • Passport, visa, and a copy of my passport in case it gets lost.

My route tonight takes me through Memphis and Amsterdam on my way to Hyderabad. If all goes well, I’ll drag into my hotel room in Hyderabad around 4:00 a.m. Saturday morning, Hyderabad time. I’ll have until Monday morning to rest up from the trip and put my game face on for a week at Microsoft. I’ll bet the Microsoft developers in India get tired of taking classes from jet-lagged instructors. But they should feel better knowing they’re not the ones having to make the trip.

Thanks to a comment left in my blog, I realized that my Enigma simulator didn't perfectly replicate the operation of a real Enigma. I have updated the code and you can download it from here. If you simply want to run the simulator, click here.

You'll notice that the letters on the rotor wheels now appear in alphabetical order. I originally had the letters scrambled, thinking they were that way on the real Enigma. (They weren't.) I have tested the revised simulator fairly extensively and everything appears to be in working order. Let me know if you discover otherwise!

Here's a test message for you to decrypt:

DOMZUY

Before you begin typing, set the rotors to A-B-C and connect E to N, A to Z, and I to L on the plugboard.

A few weeks ago, IE7 suddenly slowed down on my main PC. Each time I'd start it up, IE7 would take several seconds to get past the "Connecting..." message, meanwhile leaving me staring at a blank window. Once I got to the first screen, performance improved, but occasionally clicking a link would produce a 404 error and I'd have to click Refresh to display the page.

At first time I didn't have time to fool with it, especially since I was spending most days on the road with my laptop, where IE7 was still running normally. But when I sat down at my PC Monday morning, launched IE7, and waited 10 seconds or so for the page to appear, I really got steamed.

After verifying that certain features such as the phishing filter were turned off, I began disabling add-ons one at a time. Sure enough, the culprit came to light: The Windows Live Sign-In Helper. Disabling it using the Tools->Manage Add-Ons menu got IE7 running normally again.

Windows Live Sign-In Helper

I don't even know when that add-on was installed, but it sure is frustrating when an add-on from the same company that produces the browser makes the browser run in slow motion. If I was the IE team, I'd be ticked.

Thursday is National History Day at our local high school, and just in time for the competition, my son and I put the finishing touches on a German Enigma simulator to complement his display—written, of course, in Silverlight. Here's what it looks like:

Enigma Simulator 

Enigma machines were used to encrypt Axis military communications in World War II. There were many different versions of the Enigma; our simulator models one of the 3-rotor devices. The story of how Polish mathematicians and researchers at Bletchley Park in the UK (including Alan Turing) cracked the Enigma code is both humbling and fascinating. Historians estimate that cracking the code shortened the war by two years.

To encrypt a message, Enigma operators would begin by loading the rotor wheels (represented by the three letters at the top of the screen) into the machine and setting them to a specific code—for example, A-B-C—taken from a code book. Then they would configure the plugboard—the panel with the lettered and numbered jacks at the bottom of the screen—by cabling jacks together. The purpose of the plugboard was to strengthen the encryption by swapping letters. Connect B and C, for example, and a B typed on the keyboard was turned into a C before entering the encryption machinery. (On its way back out, the character resulting from the encryption also went through the plugboard.) Finally, the operator would type the message, and each time a character was typed, one of 26 lamps, one for each character of the alphabet, would light. A second operator would write down the encrypted message by recording the letters that lit up. The Enigma was a symmetric encryption/decryption device, meaning that an encrypted message could be decrypted by setting the machine to the same initial settings used to perform the encryption and typing in the encrypted message.

As characters were typed on an Enigma, the rotor wheels would turn, odometer-style. Because input characters were transposed as they went through the wheels, the same letter would encrypt differently each time it was entered. A simple substitution cipher might encrypt AAAAA as NNNNN. But an Enigma might encrypt the same phrase as YSKLW. Configure the rotors and plugboard differently and it could come out as GTUUK instead.

Our Enigma simulator features a keyboard, a plugboard, an output panel (replacing the 26 lamps), and three rotor wheels. Not visible, but included in the code, is a fourth, non-rotating wheel called a reflector. You can use the up and down arrows above and below the rotor wheels to set the rotors to the desired position, and you can cable plugs together by clicking on an empty plug and dragging the cable that appears to another empty plug. You can delete a cable by clicking it; not yet implemented is the ability to grab one end of a cable and move it to another plug. The simulator uses animations to make the rotors turn, and it uses a MediaElement to play typewriter clicks.

You can try out the Enigma for yourself on Wintellect's Web site, or you can download the source code and run it locally. For starters, set the rotors to D-A-D and configure the plugboard as shown above, and then type the characters displayed in the output panel to decrypt a secret message from me to you. Enjoy!

I just returned home from the PDC after a marvelous few days in sunny L.A. Sunday's Silverlight precon was a blast, and if you attended, I hope you felt it was worth your time. I could have easily filled out two more days with Silverlight fun and games, but I tried to hit the high points in the time we had together.

I spent my time on the airplane to and from L.A. updating my page-turn framework for Silverlight 2. The original framework utilized Silverlight 1.0 and was introduced in the May 2008 issue of MSDN Magazine. The new version features the same basic API with a few tweaks and additions. For example, the PageTurn class now fires a PageTurned event each time a page turn is complete, making it easy to update the UI around the page-turn canvas each time the user flips a page. Here's a sample built around the new framework:

PageTurnDemo 

You can download the sample code here, or view the app online here. The page-turn framework is implemented in PageTurn.cs, and you can see how to use the framework by perusing Page.xaml and Page.xaml.cs. The XAML structure is the same as described in the aforementioned MSDN Magazine article.

I still need to do some cleaning-up in the code and would also like to add a few more features. But since the framework's in decent shape as is, and since I have promised publicly to update it for Silverlight 2, I didn't want to wait any longer to push the bits out there. If you have comments, questions, or suggestions (or, heaven forbid, find any bugs), be sure to let me know.

I leave for the PDC tomorrow morning, but there's time for one more cool Silverlight trick before I leave.

One of the features added to Silverlight 2 late in the development cycle was the CompositionTarget.Rendering event. CompositionTarget.Rendering is essentially a per-frame rendering callback that lets you build high-performance animation loops driven by logic executed in each frame. I’ve been looking for an excuse to use it but hadn’t come across a genuine need for it. Not, that is, until today, when I suddenly found that I needed it very badly—and for something that had nothing to do with animations, but everything to do with how rendering works in Silverlight.

Consider the following code, which uses OpenFileDialog to initialize a collection of XAML image objects with image files selected by the user:

OpenFileDialog ofd = new OpenFileDialog();

ofd.Filter = "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG Files (*.png)|*.png|All Files (*.*)|*.*";

ofd.FilterIndex = 1;

ofd.Multiselect = true;

 

if ((bool)ofd.ShowDialog())

{

    foreach (FileInfo fi in ofd.Files)

    {

        using (Stream stream = fi.OpenRead())

        {

            BitmapImage bi = new BitmapImage();

            bi.SetSource(stream);

            GetNextImage().Source = bi;

        }

    }

}

It looks reasonable, and it works reasonably well, too—until the user selects 40 or 50 large image files. The problem? All this code executes on the application’s UI thread, and though the images are coming from the local file system, it can take several seconds to load them all. On the surface, you might think that the images would “pop” onto the page one by one following each assignment to Image.Source. In reality, because we’re hogging the UI thread and not giving it a chance to do any rendering, the user will see nothing until all the images have been loaded. (Incidentally, stepping a ProgressBar control as the images are loaded wouldn’t work, either. Since we’re blocking Silverlight’s ability to render, it couldn’t render the new values you assign to the ProgressBar!)

There isn’t a perfect solution to this problem in Silverlight, but there are work-arounds. If we weren’t dealing with images or other XAML objects, we could do the work on a background thread and free the UI thread to render. But since we’re dealing with images, that’s not an option.

Enter CompositionTarget.Rendering. Here’s how I restructured the code to fix the problem:

private Queue<FileInfo> _files = new Queue<FileInfo>();

  ...

public Page()

{

    InitializeComponent();

 

    // Register a handler for Rendering events

    CompositionTarget.Rendering +=

        new EventHandler(CompositionTarget_Rendering);

}

  ...

OpenFileDialog ofd = new OpenFileDialog();

ofd.Filter = "JPEG Files (*.jpg;*.jpeg)|*.jpg;*.jpeg|PNG Files (*.png)|*.png|All Files (*.*)|*.*";

ofd.FilterIndex = 1;

ofd.Multiselect = true;

 

if ((bool)ofd.ShowDialog())

{

    // Reset the queue

    _files.Clear();

               

    // Place each FileInfo in a queue

    foreach (FileInfo fi in ofd.Files)

    {

        _files.Enqueue(fi);

    }

}

  ...

private void CompositionTarget_Rendering(Object sender, EventArgs e)

{

    if (_files.Count != 0)

    {

        FileInfo fi = _files.Dequeue();

        using (Stream stream = fi.OpenRead())

        {

            BitmapImage bi = new BitmapImage();

            bi.SetSource(stream);

            GetNextImage().Source = bi;

        }

    }

}

Now each time Silverlight’s ready to rerender the UI, the application loads one image. References to the images are stored in a Queue<>, and each time the Rendering event handler executes, it retrieves one more image from the queue. Now the images pop onto the screen as they’re loaded, and the user isn’t left waiting and wondering what’s happening.

 

One of the unique features that Silverlight brings to the browser platform is the ability for you to write multithreaded apps. You can use Thread.Start, ThreadPool.QueueUserWorkItem, and other mechanisms to execute code on another thread, and you can use the same thread-synchronization primitives that you’re already familiar with from the “big” .NET Framework to synchronize your threads’ actions.

One nuance you must be aware of, however, is that Silverlight distinguishes between UI threads and background threads, and only UI threads can access the XAML DOM. When you launch a thread with Thread.Start or borrow a thread from the CLR thread pool with ThreadPool.QueueUserWorkItem, you’re using background threads that can’t touch a XAML object without throwing an exception. Even if you’re not explicitly launching threads, classes in the framework may be doing it for you. If you update a TextBlock or a bind to a ListBox in a WebClient completion event handler, for example, the update works just fine because WebClient fires events on the application’s UI thread. But if you attempt the same in an HttpWebRequest completion method, you’ll throw an exception because HttpWebRequest calls completion methods on—you guessed it—background threads.

Most texts have you remedy this situation by declaring a delegate through which a method that accesses the XAML DOM can be invoked, and then using a Dispatcher object (accessed through the Dispatcher property that XAML objects inherit from DependencyObject) to marshal back to the UI thread:

// Declare a delegate

private delegate void UpdateUIDelegate(Object state);

 

// Call UpdateUI on the UI thread

Output.Dispatcher.BeginInvoke(new UpdateUIDelegate(UpdateUI), data);

 

private void UpdateUI(Object state)

{

    // Update a XAML TextBlock

    Output.Text = "Hello, Silverlight";

}

This works, but it’s slightly unwieldy. That’s why when I need to marshal back to my application’s UI thread, I often use a DispatcherSynchronizationContext instead. You begin by caching a reference to the UI thread’s DispatcherSynchronizationContext in the page constructor. Then, anytime you’re running on a background thread and need to call a method on the UI thread, you call the synchronization context’s Post or Send method:

private SynchronizationContext _context;

       

public Page()

{

    InitializeComponent();

    _context = SynchronizationContext.Current;

}

 

// Call UpdateUI on the UI thread

_context.Post(UpdateUI, data);

This is slightly cleaner, and it offers the added option of making a synchronous call to UpdateUI (with DispatcherSynchronizationContext.Send) if circumstances require it.

Today I updated the Deep Zoom demo I originally published a few months ago for the RTW release of Silverlight 2. The new version shows how to do mouseovers on the individual subimages in a Deep Zoom scene—something that wasn't at all obvious to me how to do until I read Jaime Rodriguez's excellent blog post explaining that the order of the subimages in the MultiScaleImage control's SubImages collection mirrors the indexes in Metadata.xml. When the cursor enters a subimage in the revised demo, a caption identifying the location depicted in the image appears at the top of the page.

Deep Zoom Demo 

I'll post the source code for the sample once I figure out how to decrease its compressed size of 373 MB. I suppose I'll have to post the project without the images, but that somehow seems to defeat the purpose.

One of the areas of Silverlight that not much has been written about yet is the factoring of applications. Applications don’t have to be packaged in one big XAP file; Silverlight presents numerous options for dividing code and resources among multiple assemblies, packaging resources inside or outside the XAP file in one file or multiple files, and loading assemblies and resources at load time or on demand. And for one feature in particular, much of what has been written is wrong. It’s time to set the record straight and learn something really cool at the same time.

Suppose you’re writing a Silverlight application that uses classes in a library assembly named HelperLib.dll. You add a reference to HelperLib.dll to your project and HelperLib.dll gets embedded in the application package (the XAP file) and loaded into the AppDomain automatically. You can use types in HelperLib.dll as if they were types in your code. No problem there; it just works.

But now let’s take it one step further. Suppose you have lots of library assemblies and don’t want to swell the size of the XAP file with them because depending on how your users interact with the application, you may not need all those assemblies. To first order, the solution is simple. You deploy the library assemblies alongside the XAP file in your server’s ClientBin folder and use WebClient to download them on demand. To load an assembly after it’s been downloaded, you do this:

AssemblyPart part = new AssemblyPart();

Assembly a = part.Load(e.Result);

But what comes next isn’t very pretty. Because you didn’t add a reference to the assembly to your project, you can’t use the new operator to instantiate the assembly’s types. (Why? Because without the assembly reference, the compiler doesn’t know about the types.) So you resort to reflection—specifically, to Assembly.CreateInstance:

Object obj = (Object)a.CreateInstance("Foo");

This creates an instance of the type named Foo. But now if you want to go deeper and access some of Foo’s properties or methods, you have to perform even more reflection. This gets unwieldy fast, and as a practical matter, it means that you’ll probably give up and go back to embedding all those library assemblies in your XAP file.

Fortunately, there is a better way. The Silverlight docs on MSDN suggest that you can download an assembly, load it into the AppDomain, and still have the benefit of strong typing. The docs even offer a working example. Many people have complained that the example doesn’t work, but it does work if you run it exactly as is and don’t change a thing. The example is extremely fragile, but the docs don’t tell you why. To make matters worse, the example can fail given the right circumstances. As my friend and colleague Jeffrey Richter commented, the fact that it works at all is really more a matter of luck than anything else.

Here’s a recipe for downloading assemblies on demand and using the types in those assemblies as if they were right there in the application assembly:

  1. Add a reference to the library assembly to your Silverlight project, but change the “Copy Local” setting in the reference’s properties from true to false. This prevents Visual Studio from embedding the library assembly in the XAP file, but since the project contains a valid reference to the assembly, the compiler knows all about the types in it and will allow you to use them—even new them up.
  2. At run-time, use WebClient to download the assembly and AssemblyPart.Load to load it.
  3. Here’s the critical part. After loading the assembly, call a separate method to instantiate one of the assembly’s types, and decorate that method with a MethodImpl(MethodImplOptions.NoInlining) attribute. In addition, do not reference any of the types inside the library assembly in the method that loads the assembly. If you do, you’ll shoot yourself in the foot and what you’re trying to do will not work. Period.

Step 3 was a mouthful, and it probably makes no sense at all, so let’s look at an example. Assuming Foo is a type in a dynamically loaded library assembly, you want to be able to do this:

AssemblyPart part = new AssemblyPart();

Assembly a = part.Load(e.Result);

Foo foo = new Foo();

// Use Foo methods and properties

But even if you follow steps 1 and 2 above, you’ll be met with this:

Assembly Load Error

The solution is to restructure the code this way:

AssemblyPart part = new AssemblyPart();

Assembly a = part.Load(e.Result);

 

// Create an instance of Foo (but declare it as Object not, Foo!)

Object obj = CreateFoo();

 

// Now pass the Foo reference to another method, and in that method,

// cast the reference from Object to Foo

UseFoo(obj);

 

[System.Runtime.CompilerServices.MethodImpl

    (System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

private Object CreateFoo()

{

    return new Foo();

}

 

private void UseFoo(Object obj)

{

    Foo foo = (Foo)obj;

    // Now use Foo methods and properties all you want

}

Now it works as intended, and inside the UseFoo method, you can use a Foo as a Foo and not worry about any more casting or reflecting.

Now the big question: why does new