Monday, June 27, 2011

Using the Task Parallel Library (TPL) for Events

The parallel tasks library was introduced with the .NET Framework 4.0 and is designed to simplify parallelism and concurrency. The API is very straightforward and usually involves passing in an Action to execute. Things get a little more interesting when you are dealing with asynchronous models such as events.

While the TPL has explicit wrappers for the asynchronous programming model (APM) that you can read about here: TPL APM Wrappers, there is no explicit way to manage events.

I usually hide the "muck" of subscribing and waiting for a completed action in events with a callback. For example, the following method generates a random number. I'm using a delay to simulate a service call and a thread task to make the call back asynchronous: you call into the method, then provide a delegate that is called once the information is available.

private static void _GenerateRandomNumber(Action<int> callback)
{
    var random = _random.Next(0, 2000) + 10;
    Console.WriteLine("Generated {0}", random);
    Task.Factory.StartNew(() =>
                                {
                                    Thread.Sleep(1000);
                                    callback(random);
                                }, TaskCreationOptions.None);
}

Now consider an algorithm that requires three separate calls to complete to provide the input values in order to compute a result. The calls are independent so they can be done in parallel. The TPL supports "parent" tasks that wait for their children to complete, and a first pass might look like this:

private static void _Incorrect()
{
            
    var start = DateTime.Now;

    int x = 0, y = 0, z = 0;

    Task.Factory.StartNew(
        () =>
            {
                Task.Factory.StartNew(() => _GenerateRandomNumber(result => x = result),
                                        TaskCreationOptions.AttachedToParent);
                Task.Factory.StartNew(() => _GenerateRandomNumber(result => y = result),
                                        TaskCreationOptions.AttachedToParent);
                Task.Factory.StartNew(() => _GenerateRandomNumber(result => z = result),
                                        TaskCreationOptions.AttachedToParent);
            }).ContinueWith(t =>
                                {
                                    var finish = DateTime.Now;
                                    Console.WriteLine("Bad Parallel: {0}+{1}+{2}={3} [{4}]",
                                        x, y, z,
                                        x+y+z,
                                        finish - start);
                                    _Parallel();                                            
                                });          
}

The code aggregates several tasks to the parent, the parent then waits for the children to finish and continues by computing the time span and showing the result. While the code executes extremely fast, the result is not what you want. Take a look:

Press ENTER to begin (and again to end)

Generated 593
Generated 1931
Generated 362
Bad Parallel: 0+0+0=0 [00:00:00.0190011]

You can see that three numbers were generated, but nothing was computed in the sum. The reason is that for the purposes of the TPL, the task ends when the code called ends. The TPL has no way to know that the callback was handed off to an asynchronous process (or event) and therefore considers the task complete once the generate call finishes executing. This returns and falls through and the computation is made before the callback fires and updates the values.

So how do you manage this and allow the tasks to execute in parallel but still make sure the values are retrieved?

For this purpose, the TPL provides a special class called TaskCompletionSource<T>. The task completion source is a point of synchronization that you can use to complete an asynchronous or event-based task and relay the result. The underlying task won't complete until an exception is thrown or the result is set.

To see how this is used, let's take the existing method and fix it using the completion sources:

private static void _Parallel()
{
    var taskCompletions = new[]
                                {
                                    new TaskCompletionSource<int>(), 
                                    new TaskCompletionSource<int>(),
                                    new TaskCompletionSource<int>()
                                };

    var tasks = new[] {taskCompletions[0].Task, taskCompletions[1].Task, taskCompletions[2].Task};

    var start = DateTime.Now;            

    Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[0].TrySetResult(result)));
    Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[1].TrySetResult(result)));
    Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[2].TrySetResult(result)));

    Task.WaitAll(tasks);

    var finish = DateTime.Now;
    Console.WriteLine("Parallel: {0}+{1}+{2}={3} [{4}]", 
        taskCompletions[0].Task.Result,
        taskCompletions[1].Task.Result,
        taskCompletions[2].Task.Result,
        taskCompletions[0].Task.Result + taskCompletions[1].Task.Result + taskCompletions[2].Task.Result, 
        finish - start);            
}

First, I create an array of the task completions. This makes for an easy reference to coordinate the results. Next, I create an array of the underlying tasks. This provides a collection to pass to Task.WaitAll() to synchronize all return values before computing the result. Instead of using variables, the tasks now use the TaskCompletionSource to set the results after the simulated callback. The tasks won't complete until the result is set, so all values are returned before the final computation is made. Here are the results:

Generated 279
Generated 618
Generated 1013
Parallel: 618+279+1013=1910 [00:00:01.9981143]

You can see that all generated numbers are accounted for and properly added. You can also see that the tasks ran in parallel because it completed in under 2 seconds when each call had a 1 second delay.

The entire console application can simply be cut and pasted from the following code — there are other ways to chain the tasks and make the completions fall under a parent but this should help you get your arms wrapped around dealing with tasks that don't complete when the methods return, but require a synchronized completion context.

class Program
{
    private static readonly Random _random = new Random();

    static void Main(string[] args)
    {
        Console.WriteLine("Press ENTER to begin (and again to end)");
        Console.ReadLine();

        _Incorrect();
            
        Console.ReadLine();                                                            
    }

    private static void _Incorrect()
    {
            
        var start = DateTime.Now;

        int x = 0, y = 0, z = 0;

        Task.Factory.StartNew(
            () =>
                {
                    Task.Factory.StartNew(() => _GenerateRandomNumber(result => x = result),
                                            TaskCreationOptions.AttachedToParent);
                    Task.Factory.StartNew(() => _GenerateRandomNumber(result => y = result),
                                            TaskCreationOptions.AttachedToParent);
                    Task.Factory.StartNew(() => _GenerateRandomNumber(result => z = result),
                                            TaskCreationOptions.AttachedToParent);
                }).ContinueWith(t =>
                                    {
                                        var finish = DateTime.Now;
                                        Console.WriteLine("Bad Parallel: {0}+{1}+{2}={3} [{4}]",
                                            x, y, z,
                                            x+y+z,
                                            finish - start);
                                        _Parallel();                                            
                                    });          
    }

    private static void _Parallel()
    {
        var taskCompletions = new[]
                                    {
                                        new TaskCompletionSource<int>(), 
                                        new TaskCompletionSource<int>(),
                                        new TaskCompletionSource<int>()
                                    };

        var tasks = new[] {taskCompletions[0].Task, taskCompletions[1].Task, taskCompletions[2].Task};

        var start = DateTime.Now;            

        Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[0].TrySetResult(result)));
        Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[1].TrySetResult(result)));
        Task.Factory.StartNew(() => _GenerateRandomNumber(result => taskCompletions[2].TrySetResult(result)));

        Task.WaitAll(tasks);

        var finish = DateTime.Now;
        Console.WriteLine("Parallel: {0}+{1}+{2}={3} [{4}]", 
            taskCompletions[0].Task.Result,
            taskCompletions[1].Task.Result,
            taskCompletions[2].Task.Result,
            taskCompletions[0].Task.Result + taskCompletions[1].Task.Result + taskCompletions[2].Task.Result, 
            finish - start);            
    }

    private static void _GenerateRandomNumber(Action<int> callback)
    {
        var random = _random.Next(0, 2000) + 10;
        Console.WriteLine("Generated {0}", random);
        Task.Factory.StartNew(() =>
                                    {
                                        Thread.Sleep(1000);
                                        callback(random);
                                    }, TaskCreationOptions.None);
    }
}

Jeremy Likness

Thursday, June 9, 2011

Telerik, Windows Phone 7, Sterling, and Free Licenses

You've heard plenty about the Sterling database engine on this blog. I recently released version 1.5 which extended the reach of the database and added several feature requests. My article on Sterling for Isolated Storage on Windows Phone 7 was also recently published in MSDN Magazine. The phone has made this a very popular engine and it has been used in several production applications that you can read about in this discussion thread.

Telerik is a vendor that provides controls and tools for developers. I've used them in projects myself and favor them for Silverlight development because they are developer, designer, and MVVM friendly. In addition to controls, they provide an ORM, code analysis tools, unit mocking and testing aids, and even a free .NET decompiler. I'm also impressed by how involved with the development community they are, sponsoring many events including the one I recently spoke at, CodeStock.

To showcase the UI controls that Telerik has for the Windows Phone 7 and demonstrate how you can create a very high performance application, the team at Telerik produced a full how-to code example called "todolist." You can download the source (including a trial of RadControls for Windows Phone 7) and read the details of the project here. The mini-project demonstrates the full development lifecycle:

  1. Wireframes of what the application should look like
  2. Design from the wireframes using Metro
  3. Integration of Pivot and Panorama controls
  4. Home screen
  5. Device features such as attaching a photo and adding voice
  6. My favorite feature ... "Using SterlingDB for a blazing-fast app"

The application uses a Telerik control with a virtualized stack panel bound to a Sterling query. Because Sterling uses lazy-loaded queries (the indexes are loaded in memory but the details aren't loaded from disk until needed), the list box can scroll literally thousands of tasks ... fast. This is because the virtualized controls are bound to the lazy details, so deserialization only happens when the specific task comes into the view. You have to pull it down and play with it to see for yourself.

To help get the word out there about what Telerik's controls can do for you on the phone, as well as to continue to share the power of the Sterling database, Telerik and I have partnered to give away 10 free licenses of their RadControls for Windows Phone 7 product. All you need to do is tweet the link to this blog post along with the hashtag in the next 5 days (before 6/14/11):

#telerikwp7dev

That's one continuous set of text (feel free to provide separate hash tags for #telerik and #wp7 as well, but the tag #telerikwp7dev is what will make you eligible). Telerik pick 10 tweets that include the tag, contact the person who tweeted it and provide the details for the license.

I can't think of an easier way to pick up a set of awesome controls than to share a sample project with full source code that demonstrates an integrated Windows Phone 7 application that operates across a large, local data set. Good luck!

Jeremy Likness

Tuesday, June 7, 2011

Microsoft's Silverlight Elevator Pitch

You have heard of an elevator pitch, right? It's that quick, 30-second pitch that starts with a hook, goes on to the how, what and why and closes with a strong call to action. It's the perfect way to quickly provide the value proposition for something you're trying to sell, condensed into an easy, fast solution that you can literally share while passing floors in an elevator.

Microsoft has been selling for decades, so I assume they have a little bit of experience crafting their pitches. It turns out that they've been pitching Silverlight to us for years. But how has the message changed, and what does it mean for Silverlight developers?

Let's take a quick look at the early days just before Silverlight got it's name. Back then you had to call it by the awkward "WPF/E" which seemed to imply that Windows Presentation Foundation would eventually be found on phones and hiding inside of Linux machines. According to Microsoft (see this link) the first pitch was:

December 2006

"WPF/E "(code name) provides designers and developers with a cross-platform solution for delivering richly interactive experiences for the Web and beyond. It is a key part of the next-generation Web platform from Microsoft, delivering visually stunning and interactive user experiences. It supports multiple operating systems (including Apple Macintosh OS X) and combines 2-D animation, video, and audio within a lightweight yet flexible browser plug-in (currently under 1 MB). The XML-based presentation (XAML) makes it easy to upgrade applications that are based on AJAX (Asynchronous JavaScript and XML) to take advantage of "WPF/E." This breaks rich Web-based applications out of the proprietary "black box" in which they exist today, by using XML (XAML) for presentation and AJAX for logic.

Did they really say what was at the time an ActiveX plug-in would break applications out of being ... proprietary?

Then, Silverlight got a name ... and developers braced themselves for a wild ride.

June 2007 (all of the following quotes are archived from the Silverlight.Net site)

Microsoft® Silverlight™ is a cross-browser, cross-platform plug-in for delivering the next generation of .NET based media experiences and rich interactive applications for the Web. Silverlight offers a flexible programming model that supports AJAX, VB, C#, Python, and Ruby, and integrates with existing Web applications. Silverlight supports fast, cost-effective delivery of high-quality video to all major browsers running on the Mac OS or Windows.

This is where I believe the confusion began. CIOs trying to discern what this new thing was felt their eyes glaze over at the mention of so many languages and instead latched onto the comfortable terms of "media" and "high-quality video," then told everyone else, "Oh, it's another Flash plugin for playing movies."

July 2008

Microsoft Silverlight is a cross-browser, cross-platform, and cross-device plug-in for delivering the next generation of .NET based media experiences and rich interactive applications for the Web. By using Expression Studio and Visual Studio, designers and developers can collaborate more effectively using the skills they have today to light up the Web of tomorrow.

Thank goodness it could now run on other devices, not just platforms and browsers. XAML made it ... but ... unmanaged C++ hooks anyone? While designer and developers were mentioned earlier on, here we get the first taste of the designer/developer workflow ... made possible by XAML and Expression.

November 2008

Microsoft Silverlight powers rich application experiences and delivers high quality, interactive video across the Web and mobile devices through the most powerful runtime available on the Web.

Uh-oh, we should have seen the writing on the wall. What happened to cross-platform and cross-browser? Now we're just on the web and mobile devices? And how many mobile devices? And dangit, they keep saying "video" in their pitch making it real hard for me to sell it to line of business.

June 2009

Microsoft Silverlight is a free runtime that powers rich application experiences and delivers high quality, interactive video across multiple platforms and browsers, using the .NET framework.

Hey everyone! Look ... it's free! It's free! Not quite open source, but definitely ... free! Unfortunately, the PHP developers saw "using the .NET Framework" and ran the other way. Everyone else still called it a video player.

August 2009

Silverlight helps you create rich web applications that run on Mac OS, Windows, and Linux. Welcome to a new level of engaging, rich, safe, secure, and scalable cross-platform experience.

Now we're not just cross-platform, we've got a list of platforms. We also ditched the video, so I can finally sell line of business applications. Not only are Silverlight applications safe, but they are secure. Did we mention scalable? Enterprise, get ready ... yeah, we're talking to you.

November 2009 - from the PDC Keynote, Ray Ozzie:

Our strategic runtimes for delivering experiences across all three screens — across three screens and a cloud — are Internet Explorer and Silverlight ... And because Silverlight IS .Net, it's also the premier high level runtime for the development of and the web based deployment of line of business apps that typically need data bound controls and workflow and more...

Ah, yes! The excitement! The glory! It's their strategy now, for all of the screens, it's premier, and it's for line of business applications! This is where I wish the pitch had stayed... — thanks to John Garland for pointing out this "missed pitch."

February 2010 (to present)

Silverlight is a powerful development platform for creating engaging, interactive user experiences for Web, desktop, and mobile applications when online or offline.

And here we are today. Painfully obvious that we're no longer chasing the "cross-platform" experience. However, the key here and the reason why I love Silverlight (and the reason why customers continue to invest in it) is the fact that it does provide engaging, interactive experiences ... and the key here is both online and offline (and while it's not in the pitch, it just so happens that those experiences run really well on both Windows and Mac OSX machines).

So there you have it ... the history of the Silverlight elevator pitch.

Jeremy Likness

Sunday, June 5, 2011

The Sterling NoSQL Database in a Mango World

I was at the MIX 2011 event. There was an "Open Source Fest" before the event and I came to showcase the Sterling NoSQL Database project that I run (and code most of, although there have been numerous enhancements and patches now added by a growing team of fantastic supporters). I was happy to speak to several people who hadn't heard of the database before, not because it was unknown but because of the opportunity to introduce it to others.

There seems to be a common impression that Sterling is a database specifically designed to fill a hole on the Windows Phone 7 platform - namely, the lack of a database. That's actually not entirely true. The database was originally created to fill that hole for Silverlight in the web browser. It happened that the platform shared so much with the phone that it was an easy port (perhaps a few dozen lines of code to tweak, mostly to close the gap between the Silverlight 4 version and the Silverlight 3-ish that the phone presented at the time).

Once on the phone, it filled another gap I hadn't anticipated: the dreaded tombstone operation. People were struggling to find a consistent, easy way to serialize state and Sterling, able to handle nearly any type and depth of object graph and capable of serializing it without all of the ceremony of deriving from a custom class or splashing attributes through all of your code, was happy to oblige. It was definitely the phone that pushed its popularity.

Once people began downloading it, I started to receive a barage of questions. "What about on the server? I want something super lightweight that is object-based, not relational." "What about the local file system instead of isolated storage for out of browser applications?"

I began working on these changes. In the meantime, I wrote an article for MSDN about Sterling on the phone, was interviewed by Jesse Liberty about it and even conducted an MSDN geekSpeak about Sterling. And then it was announced: "Windows Phone 7.1 dubbed Mango will have SQL CE."

You'd almost think I'd invested everything I owned in Sterling by the way people tiptoed around me at the conference. "Jeremy, did you ... um ... hear?" "What are you going to do?"

I've been asked that enough that I wanted to write a quick little post to share what's going on. The momentum for Sterling has been picking up. If you check out the release notes for the 1.5 version, you'll see that most of the changes had nothing to do with the phone at all. In fact, 1.5 was all about reach: I brought Sterling to the server by popular demand, refactored the serialization model so the persistence model could be completely separate and based on "drivers," and then wrote drivers for memory, isolated storage, file system for elevated trust, isolated storage on the phone, and the local file system for the desktop or .Net 4.0 version. The serialization routine was optimized and extended to handle more cases than ever before and some refactoring removed some dependencies to make it even more flexible to work with your existing types (for example, you can now specify what you would like your "ignore this property" attribute to be, and proxy it to, say, an existing XmlIgnore attribute or something completely different).

The truth is, I'm excited that SQL CE has come to the phone. I never doubted it would, and I never had a goal to compete with it. That is years of brilliant developers using experience across a vast array of applications in the field to tweak and improve and create a compact, blazingly fast means of persistence on a small footprint. Not my niche. People may even be more surprised when they hear me say if it works for them, seems simple and easy and their applications use it without issue, then GO FOR IT. I'm not trying to "sell" you on Sterling (that would be rather tough for a free open source project, no?)

So what IS the story for Sterling on the phone in a Mango world? I think it's quite powerful, personally.

Is it a 2 million row story? No. 9 times out of 10 when you have that much data on your phone I think you're writing it the wrong way. What user could possibly process, need, or use that much data and absolutely HAVE to access it when offline? Most of the time a service model with a local cache holding the juicy tidbits should do just fine (and I bet you can guess what I think a good candidate for that cache will be). In the 1 out of 10 cases where it has to be that way, yes, please, find a better way to do it because I didn't write Sterling for that.

The story Sterling brings to the phone is this: extremely simple. If you already have classes that contain other classes and they reference (even with circular references) or are five levels deep and contain custom enumerations based on certain value types, great. Pass the top level object to Sterling and I'm confident it will handle it. If not, write a custom serializer for the tough parts and you're good to go.

The story is a model/behavior-based one. Sterling is about turning an object graph into bytes and back, with in-memory insights into your data to use fast queries and navigate where you need to go. You can share models between the client and server, take the bytes from one database and plop it somewhere else. The classes can have tons of behavior and Sterling won't mind - it navigates the data and worries about bringing that back. Imagine tombstoning with SQL CE and defining a set of tables with name/value pairs that you must convert into strings and back every time ... now imagine having a Tombstone<T> with a SetObject and GetObject<T> method to put any type of class there and save it ... and it works. That's the goal.

Finally, the story is about lightweight and flexible. Take a look at the binaries. Sterling is tiny - less than a few hundred kilobytes of data and lines of code in the hundreds, not tens of thousands. It has numerous extension points to allow you to plug in encryption, compression, create a custom driver that works with Azure or define your own triggers and database constraints. It's all there in a compact framework.

I'm not saying these things to brag and by no means is the system perfect. There's a lot of work to do but the community has really stood behind the implementations of Sterling to date and helped drive features. One benefit for Sterling I hadn't even imagined is the ability to create shared libraries because the API on the client, server, phone, or browser can be 100% consistent even if the underlying method of persistence is actually memory, isolated storage or the file system.

So I do think Sterling will continue to fill a gap that SQL CE doesn't - and I see some hybrid applications that use SQL CE to index references to objects and Sterling to actually serialize their complex graphs. The best of both worlds - there's no reason why the two can't work together.

What's on the road map for Sterling?

You can take a look and vote, add your own features and see the popularity of existing features here. Based on that and internal work, here's what some ideas are that the team is considering for the 2.0 release (and this will be influenced mostly by the votes on the features page, so make sure your voice is heard!)

  • Lazy loading of child objects - exploring a way to do this without using proxies or dynamic types
  • Read-only version - build a massive database, save it as a resource and then instead of saving to isolated storage, use a read-only driver to access it immediately (so no delay moving the resource into isolated storage, for example)
  • Azure drivers to use table storage
  • Internal optimizations to use a single file on disk rather than multiple files as the current version does
  • More hooks into the serialization engine to serialize types and get byte arrays without having to participate in saving
  • Dynamic table, key, and index definitions that will build these on the fly and persist them between sessions
  • Better concurrency for file-system based applications
  • Built-in synchronization (possibly through Microsoft's Synch Framework) for "sometimes connected" applications
  • Facades to expose Sterling as a cache engine
  • LINQPad support
  • MonoTouch support (same API, different platform)
  • Schema support - handling classes and types that change over time out of the box
  • ...and I haven't forgotten, I need to update the extensive 1.0 documentation to reflect the new 1.5

These are just a few items. Obviously I'm just one person with a lot of projects. The team is slowly growing as is the audience using it, so I appreciate both your ideas and your assistence if you decide you'd like to be part of the team and can help out. I think there is a rich future and right now is a great time as the team decides what 2.0 will look like.

Take care and check out the latest version - 1.5 - right here.

Jeremy Likness

Friday, June 3, 2011

CodeStock Presentation: Silverlight 5 for Line of Business Applications

A special thanks to everyone who attended my Silverlight 5 for Line of Business Applications talk at CodeStock 2011. It was a great crowd and I enjoyed meeting everyone.

As promised, here are the links to the slide deck as well as the sample project that I used to demonstrate the new features that is based on the Jounce MVVM for MEF guidance I've posted to CodePlex.

The demo includes text improvements, a composition thread example, data-binding changes, child windows, custom markup extensions and custom types. It requires the Silverlight Beta SDK and Developer Runtime to run. The session was recorded and I will post as soon as is it processed and available.

I'm looking forward to the remaining sessions today!

Slide Deck: Silverlight 5 for Line of Business

Source Code: Silverlight 5 for Line of Business

Jeremy Likness