dougherty distilled

Bryan Dougherty's thoughts on technology and software development.
in

March 2006 - Posts

Upgrading to Windows Mobile 5.0 Smartphone

I finally got around to upgrading some code originally written in Visual Studio 2003 for Windows Mobile 2003 Smartphone.  Since it wasn't straight forward, I thought it might be helpful to share my experience.

Before starting, I installed Visual Studio 2005 and the Windows Mobile 5.0 Pocket PC and Smartphone SDKs. The solution I was upgrading had one Smart Device Application project and a few referenced components.  In one of the components, I had manually referenced the System assemblies for the 1.0 Compact Framework.  The other assemblies had no notable references.

Opening the solution in Visual Studio 2005 prompted me to upgrade the code.  The conversion was successful according to the report.  I thought that maybe switching the Target Platform via the context menu option on the Smart Device Application might be all I had to do.  I was wrong.

I was running into the following error when compiling: "Version 2.0 is not a compatible version."  Figuring that this was related to the my manual Compact Framework references, I realized I had to update some of the references to the 2.0 version.  That didn't fix the issue, though.

To fix and fully upgrade the code, I had to create new projects to replace all of my old projects.  When creating the new projects, I found that you can actually now create Class Library projects specifically for the Smartphone. 

This is really nice because when adding references it only shows the Compact Framework 2.0 versions.  Taking that a step further, I could NOT reference an assembly that wasn't created this way.  After creating new shell projects and hooking up my references and resources, everything compiled and ran.  It didn't seem to run as efficiently as it did in the old emulator, though...but that may need to be a whole new topic.

A Simple Configuration Pattern

Most apps need to allow for some sort of configuration.  Using the .NET built in appSettings functionality to read settings from an app.config or web.config is perfect for simple cases.  Sometimes, though, you need to handle settings that are more complicated or repeating.  Creating section handlers can provide an elegant means of retrieving these more complicated settings. In my experience, however, using section handlers can be thought of as difficult. I thought I'd post some example code to show that it's really easy to do if you follow a basic pattern.

Step 1: Design Settings Object

Design an object that represents the settings that you'll be retrieving.  In the case of repeating settings, create a second type and add an array of that type as a parameter.  Decorate the object with XML attributes as desired. 

public class ComponentConfigObject
{
    [XmlArray(
"configItems")]
    [XmlArrayItem(
"configItem")]
    
public ConfigItem[] ConfigItems;
}

public class ConfigItem
{
    [XmlAttribute(
"a")]
    
public string A;

    
[XmlAttribute("b")]
    
public int B;


}

 

Step 2: Setup Config File

Simply add a section element to the configSections element of the configuration file.  Then add the an element with the name specified in the section element.  Inside that element add XML that represents your setting object. 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<configSections>
        
<section name="myComponentConfiguration" type="MyNamespace1.MyNamespace2.ComponentConfigSectionHandler, myAssembly" />
    </
configSections>
    
<myComponentConfiguration>
        
<ComponentConfigObject>
            
<configItems>
                
<configItem a="abcd" b="50" />
                <
configItem a="fghi" b="100" />
            </
configItems>
        
</ComponentConfigObject>
    
</myComponentConfiguration-->
    
<!-- don't need appSettings -->
    
<appSettings></appSettings>
</configuration>

Step 3: Create Section Handler

Create a class that implements the IConfigurationSectionHandler interface.  This is easy as there is just one method, Create, to implement.  All that is needed is to create our settings from the XML section provided to us.  Manual parsing of XML is a waste of time, problematic, and rarely, if ever, can I be convinced of its value.  Let the Framework do the work for you. This is why you created a settings object.  Simply instantiate a serializer and create your settings object by passing in the first child node of the XML section.

public class ComponentConfigSectionHandler : IConfigurationSectionHandler    
{
    
public ComponentConfigSectionHandler()
    {
    }
    
#region IConfigurationSectionHandler Members

    
public object Create(object parent, object configContext, System.Xml.XmlNode section)
    {
        XmlSerializer ser 
= new XmlSerializer(typeof(ComponentConfigObject));
        
XmlTextReader xmlReader = new XmlTextReader(section.FirstChild.OuterXml.Trim(), section.NodeType, null);
    
        
ComponentConfigObject config (ComponentConfigObject)ser.Deserialize(xmlReader);
        return 
config;
    
}

    
#endregion
}

Step 4: Get Settings

When it comes time to look up the settings, you simply ask for them by name.

ComponentConfigObject config (ComponentConfigObject)System.Configuration.ConfigurationSettings.GetConfig("myComponentConfiguration");

This will use the IConfigurationSectionHandler you created to return your settings.

 

See, a nice, easy and elegant way to handle a related group of settings.

Mobile Pac-Man Update On Coding4Fun

I updated the Mobile Pac-Man code and wrote an article about it for Coding4Fun.  Along with the article, I provided links to the full source code and a new release build.  The most noticable change speeds up the time it takes to start a new game.  The splash screen now displays "Loading..." while some data is crunched and cached.  After this one-time load, starting new games is faster.  I also added and About screen.  Every app needs one, right?

Here is a direct link to the article: http://msdn.microsoft.com/coding4fun/gamedevelopment/pacman/default.aspx

Local Remoting Performance

Introduction
I knew that using .NET Remoting would add some overhead compared to intra-process method calls.  I ran a little experiment to see what the performance hit would be when using Remoting within the same computer. 

Setup
I created a remotable object with some very simple methods.  The methods take a single object as a parameter and either change a couple of properties on the object or try to change the object to a new instance.  Some methods take the parameter objects by value and some are passed by reference. 

I then created three flavors of parameter objects.  The first only had two properties: a string and an int.  The second object was a more complex object which had some properties which were instances of the first object and of itself.  Finally, the third object ws even more complex, consisting of properties made of the two prior objects.  The theory I was acting on was that serialization would be a big contributor to any overhead Remoting would add. 

I ran two series of tests, one via Remoting, and one just calling the object directly.  Each method was called 5000 times with each type of parameter object.  The calls were timed to determine the average processing time per call.

Results
Not surpisingly, the meaningless methods take very little time to execute.  Within a process (i.e. no Remoting) the methods take around .03 ms.  The most complex object added only .01 ms to processing time.

Comparing those results to the processing times when using Remoting did reveal some overhead.  Method calls using Remoting and the simple object added about .7 ms per call.  The overhead increased to 2.3 ms with the most complicated parameter.  Passing the parameters by ref or by value didn't make a notable difference. 

Conclusion
As expected, Remoting adds some overhead, even without leaving a machine.  The degree of overhead increases as the parameters to the remote methods become more complicated. On the whole, however, the overhead of local Remoting is minimal, probably less than a millisecond in common situations. 

There are certainly some scenarios where local Remoting can be a good solution.  Hopefully these numbers will help you evaluate when to use it.

Pitfalls for Remoting Beginners

I recently decided to use .NET Remoting as part of a solution.  I was new to Remoting, but it was the right fit for the problem at hand. 

I was pleasantly surprised by how easy it was to get the basic Remoting functionality up and running.  The MSDN docs weren’t the clearest, though.  I think this is probably because Remoting on the whole can get very complex.  To get a little more comfortable with it, I created a test app.  I’d be happy to post it if anyone is interested in seeing a basic Remoting sample.  To satisfy some of my own curiosity, I may post comparison performance metrics between Remoting method calls with in a machine and regular intra-process calls. 

Back to the topic at hand: I ran in two pitfalls in working with Remoting.  I thought I’d share them in the hope that it saves other beginners a few lost hours.

Static Method Calls
Simply Stated: They don’t work.  Instead of the method being called on the Remote service, your application will use the in memory reference.  When you think about it, it makes sense.  There is no need to create a proxy since no instantiated object is needed to call the method.  Therefore the call doesn’t get sent out to the other process.

Passing Parameters By Value
The other issue I had was with passing a parameter by value.  I had a method on my Remoting class that took in an object and modified a few properties.  Since it is a reference type, I can just pass it in with out a ref keyword (ByRef in VB) and my method should be able to affect the properties of the object.  Here’s an example of the kind of method I’m talking about.

  public void TestChangingParameterProps(ParameterObject p)
  {
   p.A++
;
   
p.B "set p values " + p.A.ToString();
  
}

It works fine within a process, as we expect.  However, when calling this method via Remoting, the p that you pass in will not be affected.  Again, if you think about it, it makes sense.  Since the whole parameter object is being copied over (by value) to the other process and the changes are being made there, the memory locations of the properties of p can't be affected.

Hope this helps save someone some time and headaches.