5k Race Report

I’ve done many races over the past few years, but surprisingly I never participated in an actual 5K. This last Saturday was my first opportunity. It was also my first race out on Long Island in my new hometown. The race was the Sands Point 5k. The event organization was flawless from my perspective and it was a blast.

I was hoping to set a good time; in fact, I was aiming for a sub-20 minute 5k. That goal seemed doable, especially in the first two miles. That third mile was the point at which I knew it was not happening. I knew the area was a bit rugged and hilly, but I did not know to what extent. Three quarters of the third mile were actually cross country running on a beautiful trail along with soft dirt, sand, roots and wooden stairs. All in all, I was happy with my performance. I finished in 20:33.1, 21st overall and 2nd in the male 25-30 age group. Full Results here.

What follows is a description of the race itself.

I warmed up with a slow mile run; this was enough to get my heart pace going and to break a bit of a sweat. It was actually a bit humid but I did not mind. A 5k, I think, is short enough so that the humidity shouldn’t affect one as much as for a 10k or larger distance. Regardless, I did 4 strides to get the heart rate going a bit further. I lined up at the starting line; most people were shying to the back. I was trying to figure out where my correct placement should be. Ended up starting 3 rows into the crowd. I saw some of the younger kids who although young seemed like they meant business, and I tried not to mess with them. There were a lot of serious runners up there and I knew I couldn’t keep up with some of them.

Start and First Mile

The start was solid. I actually got pulled out a bit faster than I wanted to. One of the guys sped off into the distance. I was not not going to keep up with him. The fast start bothered me a bit and I settled into a solid pace. The first mile winded up a road around the center grassy field at the Sands Point preserve. Slight elevation loss and gain, but nothing bad. After a good half mile loop, we ran into the first trail loop. It was completely on the road and I felt I was going faster than I should have. There was more elevation loss and gain and I passed the first mile marker at about 6:17 into the race. I did not know whether I could sustain the pace, but I gave it what I had and pushed into the second mile.

Second Mile

The second mile finished off the first loop. I kept with the same runners throughout this time. There was a lady alongside me who kept on giving me a hard time. I thought I was breathing pretty hard and heard her too. I let her go slightly ahead, I did not want to bother racing quite yet. After passing back into the main Sands Point Preserve loop, we took a right turn on a fairly steep downhill into the gravel and dirt trails. I knew we’d be coming back us this hill later in the race and was not looking forward to it. The downhill gave me a chance to catch my breath but before I knew it I was working again. Passed the mile 2 marker at about 12:38.

Third Mile
This time we were on dirt trails that had sand and roots. As we kept on going deeper, it kept on getting narrower and steeper. Up and down we went. At one point we were climbing up wooden stairs. I felt myself slowing. At this point I was fairly sure I wouldn’t be breaking 20 minutes. There was a 13 years old in front of me making who also was slowing a bit. As we ran through the woods and finished off the loop, I really wasn’t looking forward to running up the hill. Little did I know, my recent hill training seemed to help a bit. I passed 2-3 (things were getting hazy, I’m not sure) runners up this hill. We were back on the first loop of the preserve’s grassy field. I think we were at about .65-.70 of the third mile at this point. Unforunately, the part from here to the finish was also slightly uphill. I gave it what I had. As we neared the mile 3 marker, things were very hazy. I thought of slowing down but knew I was way too close to do that. I slightly remember seeing 19:50 on the marker as I was nearing it. There was a sharp left turn onto a grassy area with a sprint to the finish line. I did not know I had it in me but I really sprinted. It felt good. I saw one guy, I zeroed in on him and just ran my guts out. I remember the finish line announcer mentioning something about a sprint but I don’t remember much else.

Finish
I passed the finish line, gasped for air and grabbed some water. I didn’t look at the time, just kept on trying to catch my breath and walked around. I felt I was gonna lose all control over my body. I couldn’t swallow water, I thought I would throw it up. In time, felt better, ate two bananas and juice and saw the results. I was happy. 20:33.1 maybe shouldn’t make you as beat up as I was, but it sure felt good to finish strong. All in the middle of a 56 mile week. I’m hoping that after the marathon I can take a bit of time off and then concentrate on improving my 5k times; it would be a lot of fun to set that sub 20 minute goal. With proper training, maybe even a sub 19.

Runner’s High

My training has been going well, though not as well as I’d like to. The time and energy required to properly train for a marathon is somewhat ridiculous. It’s not really possible for me to stop my wife’s and my life just so I can run 50 miles every week. That being said, I have not been doing the marathon pace runs, which is a bit intimidating. There are still 10 weeks left, so I will make sure I get a few of those in before the event itself. That being said, I think I am doing fine mileage-wise. Had a bit of an off-period because of a family vacation and not feeling well the week before that. Overall, very satisfied. My monthly mileage for the months of April, May, June and July has been: 141, 141, 139, 125 (cruise week…). This month, I am on pace to hit a solid 150+ miles, which is very encouraging. On August 28th I am racing the Bronx Half Marathon, so it should give me a solid indication of where I stand, with about 6 weeks to go to the marathon.

The other reason my training has not been satisfactory is the heat. This summer has been a real drag and the hot weather means my pace has been slower than what I’d like to see at this point. May average pace for the 141 miles was a nice 7:53 min/mile, where as July’s 125 miles were at about 8:15 min/mile. Not a huge difference, but it certainly feels like it. Because of this it has been somewhat difficult to really get an indication as to where my fitness stands. This morning, I think I got a good idea.

This week I am in the middle of my first 50+ mile week. Monday morning I ran 8 miles, Tuesday morning I ran 10 and this morning I ran about 7.5. Add to that the fact that I moved (more on this in a later post) and I have a lot more hills to deal with. My average pace for Monday was 8:29 min/mile. Rather slow. However, my fastest mile being at a solid 7:37 min/mile. Every other mile was slower than 8 min/mile. Tuesday’s 10 mile run was slightly faster at an average pace of 8:20 min/mile. The fastest two miles were at 7:35 and 7:41. Slightly better. This morning’s results were noteworthy though. I woke up feeling sleepy, thinking about delaying the run until tomorrow. Ended up running the 7.5 distance at an average 7:45 min/mile. The middle 5 miles were all below 7:30 min/mile, with the fastest one at 7:01 mile/mile. That is great.

What was different? For one, its the first time I was listening to music while running. That really helped. I felt so fast and definitely hit the running high. Second, although humid, the temperature was a good 70 degrees and it was fairly breezy. Can’t wait to see how I can run with a taper and the temperature on October 10th. Not expecting a 3:10 marathon, but am hoping for anything less than 3:20. August 28th will be a good check in on that goal. Signed up for a local 5k this Saturday, I’ll write the results up afterwards.

Training for a marathon

Non-technical post coming up… So after 4 years of on and off running I finally committed to training for a marathon. The date is Saturday, October 15 in Hartford, CT. It will be the first marathon but I have huge expectations. There are seventeen weeks left but I’ve been consistently upping my mileage for the last three months. I am aiming to finish in under 3:20, but a Boston qualifying 3:09:59 would be amazing.

I used to spend time obsessing over schedules, mileage and paces. Over the past 4 years I’ve learnt a lot about what my body can handle in terms of running and how much recovery time I need. For the marathon, I am stripping the training down to a few fundamentals.

  1. Rest and recovery:The most important aspect of the training will be to rest and recover throughly to be able to handle the solid 18 weeks of training. Whenever I used to run high mileage weeks before, I used to do it before work. After work my motivation was lower and it was hotter. But early runs meant that my sleep suffered. No more. I will now work out during the week during lunch time. I can do this in my current position.
  2. Alternating hard and recovery weeks: If there is one thing I have noticed, it is that I cannot keep a high mileage, hard pace schedule for more than two-three weeks before my body starts breaking down. Mileage alone is tough, especially with 15+ mile long runs on the weekends. If you add tempo runs and some speed sessions, I do not think I’d be able to handle it all. So the goal is to alternate the difficulty of the weeks to allow for proper recovery.
  3. Long runs: The long run is the staple of any marathon training regimen. My plan is to max out at 20 miles. Incidentally, I have already ran one 20 miler. With 17 weeks left, this is great news. I run the run at a decent pace which ranges on the top end at about 8:20 and can go as low as 7:45 when I am feeling well. Hydration is a big problem for me on these runs. I lose a lot of water weight when I run and drinking while running is a bit difficult. I survived the last 20 miler on 40oz of Orange Gatorade. I think I should up it to a total of 50-60oz, by adding water to the gatorade. Now that NYC parks water fountains are on, this should be easy.
  4. Lactate Threshold run: I want to do a weekly LT run. (flagrant simplification coming…) The purpose of these is to train the body to clear out lactate at a quicker pace, thus, enabling me to run at a quicker pace for a longer period of time. Even though I can finish 20 miles at an average 8:00min/mile pace, BQ pace is 7:13. I’m sure I could keep up a 7:30 pace, but the LT runs should help me get down to the 7:13 pace. One of these a week. Basically, need to run at 6:30-6:50 pace for 20-40 minutes. I ams tarting at 20 minutes, but plan to extend as my training progresses.
  5. Speed Sessions: Although not as important as long and LT runs, the speed workouts will help in increasing the amount of oxygen my lungs can take in as develop my leg muscles. There will be two types of workouts: 100m strides at 95% of my max speed and 800m-1200m repeats at 5k pace. Speed is always fun.
  6. Marathon Pace runs: If I want to run 26.2 miles at a 7:13 pace, I need to train my body to run at that pace. On my recovery weeks in which I do not do a 20 mile run, I want to run 10+ miles at MP. Slowly, I want to increase this to up to 16 miles. The ideas is just to teach the body what 16 miles at 7:13 pace is like.
  7. Taper: The last 2-3 weeks before the marathon will be a solid taper. My body will need to recover from the challenging training and peak for the marathon. If I can run 20 miles while relatively tired, being fully rested should allow me to pull off the marathon at 7:13.

As long as I stay true to these points, I can achieve my goals of a sub 3:20 marathon and maybe a 3:10. Every week, I plan to keep a journal on this blog of how the training is going. I know it won’t be pretty, but come October, I will definitely be in the best shape of my life.

Dynamic .Net Licensing

.Net application licensing is an interesting topic. Many third party components have a run-time licensing model based on compiled license files. The idea is that you build your application executable and embed a compiled licenses resource into the assembly. During runtime, the third party components retrieve the executable assembly using Assembly.GetEntryAssembly() and attempt to open the license resource. If the license inside this resource is valid, the component works fine. Otherwise, a licensing exception is thrown.

The problem

This approach to embedding licenses is static. This is ok if you are building a monolithic application. If you are working in an environment that is a bit more dynamic, for instance, anything based on a composite UI, this is not sufficient. If there is one shell executable that does not know what modules will be loaded into it and what their dependencies are, there is no way we’re going to embedded license files ahead of time. A more dynamic approach is needed.

Solution

The solution is fairly simple once a few points are made.

  • The license files created by the license compiler are simply serialized Hashtable objects that map a full type name to some license value.
  • The compiled license file is just an embedded resource with the name [exeuctableassembly].licenses.
  • If the framework is unable to find a resource, it raises the AppDomain.ResourceResolve event. This event needs to return the Assembly that contains this resource.

To dynamically make this work, we can:

  1. During startup, read in the licenses and serialize the Hashtable into a .licenses text file.
  2. Create a dynamic Assembly and embed the resource. Since dynamic assemblies do not support the GetResource methods, we save the assembly to disc and then load it as a normal assembly.
  3. Whenever the licenses file is requested and ResourceResolve is raised, return the new assembly.

I will leave points 2 and 3 for you to solve since they are fairly straightforward, but how do we properly serialize the Hashtable? Turns out that the easiest solution it to place the license compiler into Resharper and figure out how this application does this. This approach has saved me quite a lot of time. I don’t have the code handy but send me an e-mail if you need some direction.

WPF UIElement caching in the ContentControl

In a previous post I outlined an approach to abstract away the creation of a View for a ViewModel. I find this approach very elegant and we have successfully used it on a project. However, you can run into an issue with it because of how WPF’s ContentControl caches View instances.

Let’s assume that we are using the approach specified in the post. We are creating a clock application. We have a View called ClockView and a corresponding view model called ClockViewModel. Our main Window.xaml is the following:

<Window ...>
    <Window.Resources>
        <DataTemplate DataType="{x:Type app:ClockViewModel}">
            <app:ClockView />
        </DataTemplate>
    </Window.Resources>

    <ContentControl x:Name="MainContent" />
</Window>

Our Window.xaml.cs contains:

MainContent.Content = new ClockViewModel();

In this scenario, the ContentControl will correctly render the View. However, if at any time we assign the ContentControl’s Content property to be a new instance of the ClockViewModel class, the constructor for ClockView WILL NOT be called. A new instance is not created. Instead, the first View is recycled.

Why does this occur? It is useful to examine the DataTemplate class. The class is a container for a visual tree of objects to create. The visual tree is stored in the DataTemplate.VisualTree property; the type if a FrameworkElementFactory. When the method DataTemplate.LoadContent, is called, an instance of the Visual Tree is created. ContentControl calls this method only once for the corresponding DataTemplate. This is why we see he ClockView be constructed only once.

If the Content of the ContentControl is changed at runtime, the same View will be reused. If state is stored in both the ViewModel and the View, the screen may become out of sync. There are a few approaches to solving this issue:

  1. The ViewModel should contain the entire state of the screen. Every UI element in the View should derive its properties through bindings. This approach is in line with the zero-codebehind approach. This can certainly be taken too far as we don’t want logic and properties that belong to the View (such as details of animations, etc) to end up in the ViewModel.
  2. Since the first approach might not always make sense, the UserControl should correctly handle the DataContextChanged event. In the handler, the View should properly refresh its inner state form the new DataContext.

Creating ViewModel to View mappings

One of my favorite approaches to creating View/ViewModel pairs in WPF it to use data templates. Say you have a ViewModel called MyViewModel and it should be displayed in the UI as the View MyView.

We can create a fairly straightforward DataTemplate defined as:

<DataTemplate DataType="{x:Type local:MyViewModel}">
  <local:MyView />
</DataTemplate>

Whenever we add the ViewModel instance into a Window or a ContentControl, it will render using the DataTemplate, which just happens to be the View.

If we ever run into a dynamic scenario in which we are unable to easily add static XAML as a resource dictionary into an existing resource dictionary, as we might in a Prism module scenario, we can use the following method instead. Just declare it in our MainWindow or Application and expose it through an interface inside that can be accessed through a service container.

public void RegisterViewModelToViewMapping()
{
    DataTemplate template = new DataTemplate(typeof(TViewModel));
    template.VisualTree = new FrameworkElementFactory(typeof(TView));

    DataTemplateKey key = new DataTemplateKey(typeof(TViewModel));
    Resources.Add(key, template);
}

WPFying DataRow

Our team encountered a strange issue recently. We have a strongly typed DataSet. We observed inconsistent behavior when binding our UI to DataRow objects or the DataRowView for those rows. In particular, WPF did not appear to refresh all the bindings when the DataRow’s column values changed. We also observed that property change notification on the DataRowView class did not work as expected.

We came up with a quick solution: WPFify the DataRow object. By this, we mean, have our DataRow class implement the INotifyPropertyChanged interface. Since the generated strongly typed DataRow is declared using partials, we are able to extend the class in another file. The fix is to simply handle the Table.ColumnChanged event and raise the corresponding INotifyPropertyChanged.PropertyChanged event.

        partial class MyDataRow : DataRow
        {
            ........... // auto generated contents
        }

        partial class MyDataRow : INotifyPropertyChanged
        {
            public void Wpfify()
            {
                Table.ColumnChanged += new DataColumnChangeEventHandler(HandleColumnChanged);
            }

            private void HandleColumnChanged(object sender, DataColumnChangeEventArgs e)
            {
                if (e.Row == this)
                {
                    OnPropertyChanged(e.Column.ColumnName);
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string propertyName)
            {
                var ev = PropertyChanged;
                if (ev != null)
                {
                    ev(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

For our purposes, this has behaved well and has gotten rid of our problems with DataRow notifications.

WPF Dispatcher Frames

A few months ago, I read into some advanced WPF threading topics. One that had been particularly confusing to me is the idea of a DispatcherFrame. I hope that this article can shed some light on what it is, how they can be used and why we should care.

Message Loops

Win32 applications revolve around the concept of a message loop. Any interaction that occurs with it, be it a a mouse over, a keyboard event or a paint message, is queued up and the application needs to process it. The UI thread is responsible for retrieving the operation from a queue and correctly executing it. HIstorically speaking, the concept of an event loop has been around for a long time. For more background on the Win32 message loop, see here.

A sample message loop in Win32 looks like this:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

The message loop is a central concept in the Win32 API. Frameworks like Windows Forms and WPF attempt to abstract these concepts as much as possible: WinForms is just a managed wrapper around this. Although WPF is a step into the managed world, it still revolves around the concept of a message loop.

The Dispatcher

Any WPF application has a Dispatcher object associated with it. A Dispatcher object is a wrapper around the application’s message loop. In fact, with a little bit of exploration, you can find this little gem:

while (/* intentionally left out for now*/)
{
   if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
   {
       break;
   }
   this.TranslateAndDispatchMessage(ref msg);
}

The queue of DispatcherOperations is processed from this queue. A method like Dispatcher.BeginInvoke simply inserts a DispatcherOperaton into the loop.

So what are these frames?

A DispatcherFrame is a message loop inside the Dispatcher. The Dispatcher essentially has a stack of DispatcherFrames that it uses the execute the queue of DispatcherOperations. The topmost frame is the frame responsible for the current queue processing. The only way for a frame to terminate is if its Continue property is set to false.

The main functionality a DispatcherFrame provides is the ability to block a UI operation, while the system can continue to process UI events. The blocking call is the call to Dispatcher.PushFrame(DispatcherFrame).

Let’s reveal another part of the gem mentioned above:

public static void PushFrame(DispatcherFrame frame)
{
    ...

    while (frame.Continue)
    {
        if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
        {
            break;
        }
        this.TranslateAndDispatchMessage(ref msg);
    }

    ...
}

Pushing a frame starts a new message loop inside the current message loop. So we aren’t looking really at some internal Stack<DispatcherFrame>, but rather at a stack of PushFrame method calls. To reiterate, PushFrame blocks the current call but keeps on processing other GUI events.

The implementation of Dispatcher.Run is pretty clear:

PushFrame(new DispatcherFrame());

So what?

Why do we need nested loops to execute our UI? There are few examples out there. A while go, Kent Boogaart wrote an interesting post in which he illustrates one such case.

I’m not entirely sold on whether this is the only approach to this problem. One certainly has the ability to use Window.ShowDialog() though the blocking of the Main Window might be an issue. If you are executing a method on the UI thread and this method requires message pumping, then PushFrame is what you are looking for.

There are other things that can be done with PushFrame, like something similar to Application.DoEvents as described in the MSDN docs.

I hope that this article has provided some clarity on this rarely used part of the WPF Threading model.

Controlling UI using power shell (part 1)

Ever since PowerShell was released, I’ve been very interested in the technology. Coming from a linux background, I love the command line. And, let’s face it, cmd is shameful.

I have been imagining a UI environment in which at any point, anyone can enter into a command line and have access to all of the objects in the application. If you are following the MVVM design pattern, you could get an instance of the view model and change properties on it or invoke commands.

PowerShellMVVM

Using the PowerShell 2.0 SDK, this is possible. There are a number of ways of implementing this functionality. In this and a few additional posts, I will cover a large amount of the PowerShell 2.0 SDK, and a few implementations of the desired functionality.

What is PowerShell

PowerShell is Microsoft’s new command line shell and scripting environment. It’s better than cmd in many ways and inherits a lot of ideas from unix shells. The thing that attracted me most to the shell is that it is based on the .Net framework. Scripts and commands in PowerShell don’t return text, but, they return .Net objects.

PowerShell SDK: basics

PowerShell 2.0 includes the PowerShell SDK. There are a number of classes in the System.Automation.Management Assembly that allow you to build various custom features. For example, you can create custom PowerShell commands known as Cmdlets and you can also implement PowerShell Providers. PowerShell then allows you to create a custom PowerShell SnapIn. Activating a PowerShell SnapIn in a PowerShell instance will expose all Cmdlets and Providers registered in the snap to the PowerShell instance.

There is an additional set of PowerShell classes under the System.Management.Automation.Runspaces that allow us to programmatically create an in-memory instance of PowerShell. The developer would create a Runspace, which is a factory for execution Pipelines. Each pipeline is able to execute scripts or commands.

An interesting point about Runspaces, is that they support programmatic addition of SpanIns. You can register your Cmdlets with your Runspace and use scripts that invoke your Cmdlets. Runspaces also support registering variables.

A first attempt

My first attempt at a integrated UI and PowerShell environment was based on the knowledge of the SDK above. This approach is not horribly wrong, but does not work in numerous cases. I will explain further in my next post. The final result was a WPF user control called PowerShell.Wpf. The image in the beginning of this post illustrates a session in this control. I register my ViewModel as the variable “vm” in the Runspace. It is then exposed in the instance and I can use it and modify it. In the sample above, I have changed the Data property of the view model. This change is reflected in the UI itself.

The rest of this article describes the implementation of the PowerShell control.

PowerShell.Wpf implementation

The user control is implemented as a MVVM component. The View is simply a readonly TextBox in which we show the commands invoked and their output. Below, is a single row TextBox that allows us to insert commands. The control supports 3 commands: Execute, LoadPrevious and LoadNext. LoadPrevious and LoadNext allow us to use the up and down arrow keys to navigate over the command history. The Execute command executes the PowerShell command.

Each command executed in the UI is represented by the PowerShellCommand class. This class stores the original command string, the time when it was executed and the result. For the implementation of command history, a command can also be based on a previous command.

The CommandHistoryManager class is able to manage the history of all executed commands and its string representation, which is the string that is displayed in the output TextBox.

PowerShellSessionManager is the meat of the implementation. The constructor opens up the Runspace in which every command will execute and there is a method that allows clients to register session variables with the Runspace.

public PowerShellSessionManager()
{
    Runspace = RunspaceFactory.CreateRunspace();
    Runspace.Open();
}

...

public void RegisterSessionData(string name, object value)
{
    Runspace.SessionStateProxy.SetVariable(name, value);
}

When a script is ready to be executed, we the ExecuteCommand(PowerShellCommand) method is called.

public string ExecuteCommand(PowerShellCommand command)
{
    var pipeline = Runspace.CreatePipeline();

    System.Collections.ObjectModel.Collection<PSParseError> parseErrors =
        new System.Collections.ObjectModel.Collection<PSParseError>();

    var parsedTokens = PSParser.Tokenize(command.Command, out parseErrors);

    if (parseErrors.Count > 0)
    {
        var report = BuildErrorReport(parseErrors);
        Debug.WriteLine(report);
        return report;
    }

    Command c = new Command(command.Command, true);
    pipeline.Commands.Add(c);

    IEnumerable<PSObject> result = null;
    try
    {
        result = pipeline.Invoke();
    }
    catch (RuntimeException e)
    {
        string message = string.Format("Found error while trying to invoke command.\n{0}", e.ToString());
        Debug.WriteLine(message);
        return message;
    }

    var resultStr = BuildResultOutput(result);
    return resultStr;
}

private string BuildResultOutput(IEnumerable<PSObject> result)
{
    var builder = new StringBuilder();

    foreach (PSObject resultObj in result)
    {
        if (resultObj == null)
        {
            builder.AppendLine("[null]");
        }
        else
        {
            var temp = resultObj.ToString();
            builder.AppendLine(temp);
        }
    }

    var resultStr = builder.ToString();
    return resultStr;
}

A few useful points:

  • The PSParser.Tokenize method can be used to verify whether there are any syntax errors in your script.
  • There are a few ways to create Command objects to execute commands. The object can be constructed with just the command name and each parameter/argument must be passed in using the object model. This is a lot of work and involves parsing the string. Fortunately, the class supports any input string as long as the second boolean argument is set to true to indicate that the string is a script.

The full code for the PowerShell.Wpf control and the sample can be found here.

A WPF Splash Screen

When I was first looking into displaying a splash screen in a WPF app, I found a large number of examples using some managed code. I then found some samples using .Net 3.5 Sp1’s WPF Splash Screen implementation. None of these really suited my requirements. We weren’t looking for only displaying an image. We were looking to display some sort of status for the users and, quite frankly, for ourselves. We wanted the flexibility to display any WPF content and, more importantly, we had other initialization logic that needed to execute on the UI thread!

The motivation

The UI was a composite UI and we were initializing numerous plugins. At first, the shell displayed the Main Window and then we called the Initialize() logic for each plugin. The problem was that plugins were able to do anything in the initialize code, including calling services, initializing controls, etc. The resulting behavior was a window that was unresponsive and looked frozen until all plugins were initialized. Even if they did not do things on the UI thread, initializing over 8 plugins was not seamless (load from disk, JIT some code, etc). We decided that we did not want to suffer the frozen main window on startup curse. Instead, let’s initialize everything first and only show the window once everything is good to go.

Only now we had nothing on the screen for some time. The solution: a splash screen that can display messages and allow execution to occur on the UI thread. Since there was one large initialization method executing on the main UI thread, we did not want to bring in a complex splash screen that needs message pumping on the same thread.

Solution

The solution is fairly simple. A WPF app has one main UI thread. However, we are able to create any number of separate, independent UI threads. The solution is to create a new STA thread in which we run a separate Dispatcher that hosts the splash screen window. In retrospect, this would have been a perfect place to use the power of DispatcherFrames, but I’ll address this in a future post.

Our client code should be something like this:

using (ISplashScreen splashScreen = SplashScreenManager.CreateSplashScreen())
{
    // do lots of work on UI thread
}

with ISplashScreen defined as:

/// 
/// Contract through which client application can talk to the splash screen
/// 
public interface ISplashScreen : IDisposable
{
    /// 
    /// The text message being displayed in the splash screen
    /// 
    string Message { get; set; }

    /// 
    /// The content object displayed in the splash screen window
    /// 
    /// 
    /// This method sets the Content element in the Splash Screen. Cannot
    /// accept an object because any UI element needs to be initialized in
    /// the splash screen's UI thread.
   void SetContentObject(Type objectType);
}

The idea behind SetContentType is that we are unable to set the Content of the screen directly, since the UI element would need to be created in the same thread and the splash screen. For simplicity, we assume the content object is static (maybe an image) and simply have the splash screen manager initialize the type.

The magic behind CreateSplashScreen is pretty straightforward.

public class SplashScreenManager
{
    private static object mutex = new object();

    public static ISplashScreen CreateSplashScreen()
    {
        lock (mutex)
        {
            SplashScreenWindowViewModel vm = new SplashScreenWindowViewModel();

            AutoResetEvent ev = new AutoResetEvent(false);

            Thread uiThread = new Thread(() =>
            {
                vm.Dispatcher = Dispatcher.CurrentDispatcher;
                ev.Set();

                Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate()
                {
                    SplashScreenWindow splashScreenWindow = new SplashScreenWindow();
                    splashScreenWindow.DataContext = vm;
                    splashScreenWindow.Show();
                });

                Dispatcher.Run();
            });

            uiThread.SetApartmentState(ApartmentState.STA);
            uiThread.IsBackground = true;
            uiThread.Start();
            ev.WaitOne();

            return vm;
        }
    }
}

The result is a splash screen with its own UI thread. We use the MVVM pattern in the background. The SplashScreenViewModel object is the Window’s ViewModel and implements the ISplashScreen interface for clients.

The CreateSplashScreen method creates a new Background STA thread. This thread queues up the SplashScreenWindow initialization code and runs the Dispatcher on the thread. As soon as the Dispatcher is ready, the splash screen will show up. The ViewModel’s Dispatcher object must be set before we can call SetContentObject(Type) on it (this method needs to create the Type using the Dispatcher object), so we synchronize between the calling thread and the splash screen initialization thread so that Dispatcher will always be set when the ISplashScreen instance is returned.

The library currently only supports a rectangular window with static content. It should be fairly easily to modify this library to support non-rectangular windows and dynamic content, as long as all UI operations are somehow executed on the splash screen’s Dispatcher.

Notes

  • Performance is not a real consideration for this approach to the splash screen. The idea here is not to shave milliseconds off, but rather provide some feedback to the user. We prefer to display something live to the user as soon as possible rather than worry about milliseconds during start up. On a fast machine, the extra time spent to spin off a new thread and display the splash screen is not significant.
  • At one point, we had our UI initialization logic spread across two AppDomains. In that case, the splash screen manager class inherited from MarshalByRef and we were able to share one instance across multiple AppDomains.

You can download the library here.