Software Development

My First OpenRasta Project – Part 1

On the OpenRasta Wiki there are some instructions on getting your project up and running the manual way, should you so wish. One of the new features introduced at the last beta was a Visual Studio 2008 project template, which installs as part of the binary distribution.

Once installed you can create an OpenRasta project by going to the “Visual C#” Project Types and selecting OpenRasta ASP.NET Application (3.5) from the templates on the right of the dialog.

OpenRasta: New Project

Once the project is created you’ll see that it has set the project up, added the references to the assemblies that it needs and created an initial handler, resource and views.

OpenRasta: Solution Explorer

Before continuing further a little explanation of what each of these things are is in order.

A resource is a source of information. It is referenced via a URI. This blog post is a resource, an image is a resource, an invoice is a resource. However, a resource does not imply any particular kind of representation. In terms of OpenRasta a resource is simply an object

A handler is an object that manages the interaction of the resources. In MVC parlance it would be the “C” or controller.

A view is a regular ASP.NET page that can be rendered via the WebFormsCodec. It is not compulsory to implement any views at all if you don’t need ASP.NET.

A codec is the class responsible for encoding and decoding the representation of a resource. The built in codecs are WebForms, JSON and two types of XML.

First Code

When you get started you’ll need to configure OpenRasta. It needs to know the details of the resources you want to expose and the handlers that can deal with those resources. To do that OpenRasta looks for a class in your project that implements the IConfigurationSource interface.

If you have two or more classes that implement this interface then the first one that is found will be used. As the project template already contains a Configuration class already set up and ready to go there is nothing additional to do other than set the configuration.

In the example I’m going to show, we will be rendering an invoice. So the configuration needs to look like this:

public class Configuration : IConfigurationSource
{
    public void Configure()
    {
        using (OpenRastaConfiguration.Manual)
        {
            ResourceSpace.Has.ResourcesOfType<Invoice>()
                .AtUri("/invoice")
                .HandledBy<InvoiceHandler>()
                .AsXmlDataContract();
        }
    }
}

The configuration happens through a fluent interface. The ResourceSpace is the root object where you can define the resources in your application, what handles them and how they are represented. In this case this is going to be a fairly simple example. As it is a fluent interface it does seem to be fairly self explanatory.

The Invoice class is a simple POCO DTO that represents an invoice. POCO means Plain Old CLR Object and DTO is a Data Transfer Object. In this example the Invoice just looks like this:

public class Invoice
{
    public string Reference { get; set; }
}

The InvoiceHandler class is another POCO that happens to have methods on it that are picked up by the use of conventions. If you have a method named after an HTTP verb (like GET or POST) then OpenRasta will use it to handle that verb.

In this example we are just going to return a simple Invoice object. I don’t want to complicate the example with other things at the present, so it will, in fact, always return an invoice with the same Reference property value.

public class InvoiceHandler
{
    public Invoice Get()
    {
        return new Invoice
        {
            Reference = "123-456/ABC"
        };
    }
}

As the configuration specified that the XML Data Contract codec was to be used the invoice is rendered using that codec. The output looks like this:

<?xml version="1.0" encoding="utf-8"?>
<Invoice xmlns:i="http://www.w3.org/2001/XMLSchema-instance"          xmlns="http://schemas.datacontract.org/2004/07/MyFirstOpenRastaProject.Resources">
  <Reference>123-456/ABC
</Invoice>

Obviously at this stage it isn’t very useful. This is just a quick demonstration showing how quickly something can be set up. In coming parts I’ll be addressing other issues that so that more useful things can be done.

 

NOTE: This blog post is based on OpenRasta 2.0 Beta 2 (2.0.2069.364): [Download]

Technorati Tags:
Software Development

Dynamic Objects in C# 4.0

It seems only very recently that I was posting about this wonderful new feature in C# 3.0 called LINQ and its associated language features such as anonymous types, object initialisers and lambda expressions. Soon C#4.0 will be released and it has a host of new goodies to look forward to.

So far I’ve just been dabbling with dynamic types and the dynamic keyword.

C# has been up until this point a purely statically bound language. That meant that if the compiler couldn’t find the method to bind to then it wasn’t going to compile the application. Other languages, such as Ruby, IronPython, Magik and IronSmalltalk are all dynamically (or late) bound where the decision about where a method call ends up is taken at runtime.

Now if you declare an object as being dynamic the compiler will hold off, just as it would do naturally in a dynamic language. The method need not exist until runtime. The binding happens at runtime. SnagIt CaptureIf, like me, you rely heavily on intellisense to figure out if you are doing the right thing then you are going to have to get used to not having it. Since the call will be bound at runtime the compiler (and of course intellisense) won’t know whether a binding is valid or not. So, instead of regular intellisense you get a message simply saying “(dyanmic expression) This operation will be resolved at runtime.”

So, how do you get started with dynamic objects? I suppose the simplest example would be an object graph that is built at runtime that would normally have a fairly dynamic structure, say a nice XML file.

In this example, I’m going to take an XElement object (introduced in .NET 3.5) and wrap it in a new object type I’m creating called DynamicElement. This will inherit from DynamicObject (in the System.Dynamic namespace) which provides various bits of functionality that allows late binding.

using System.Dynamic;
using System.Linq;
using System.Xml.Linq;

namespace ColinAngusMackay.DynamicXml
{
    public class DynamicElement : DynamicObject
    {
        private XElement actualElement;

        public DynamicElement(XElement actualElement)
        {
            this.actualElement = actualElement;
        }

        public override bool TryGetMember(GetMemberBinder binder,
            out object result)
        {
            string name = binder.Name;

            var elements = actualElement.Elements(name);

            int numElements = elements.Count();
            if (numElements == 0)
                return base.TryGetMember(binder, out result);
            if (numElements == 1)
            {
                result = new DynamicElement(elements.First());
                return true;
            }

            result = from e in elements select new DynamicElement(e);
            return true;
        }

        public override string ToString()
        {
            return actualElement.Value;
        }
    }
}

The key method in this class is the override of the TryGetMember method. Everytime the runtime needs to resolve a method call it will call this method to work out what it needs to do.

In this example, all that happens is that if the name matches the name of a child element in the XML then that child element is returned. If there are multiple child elements with the same name then an enumerable collection of child elements is returned.

SnagIt CaptureIn the event that there is no match the method defers to the base class. If the binding fails then a RuntimeBinderException is thrown.

However, if the binding works you can make complex or ugly calls look much easier. For example. This program using the DynamicElement class to read the contents of an RSS feed:

using System;
using System.Xml.Linq;
using ColinAngusMackay.DynamicXml;

namespace ConsoleRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            XElement xel = XElement.Parse(SampleXml.RssFeed);
            dynamic del = new DynamicElement(xel);

            Console.WriteLine(del.channel.title);
            Console.WriteLine(del.channel.description);

            foreach (dynamic item in del.channel.item)
                Console.WriteLine(item.title);

            Console.ReadLine();
        }
    }
}

The program starts off by reading in some XML into a regular XElement object. It it then wrapped up into the DynamicElement object, del.

The variable del is declared as a dynamic which lets compiler know that calls to its members will be resolved at runtime.

The program then uses the dynamic object to very easily navigate the XML. In this example, I’ve used the XML of the RSS feed for my blog.

The output of the program is:

SnagIt Capture

 

The barrier to entry for creating and using dynamic objects is quite low. It will be quite interesting to see how this new feature plays out.

Many people like the additional comfort that static binding at compile time provides as it means less things to go wrong at compile time. Advocates of dynamic binding often argue that if you are doing TDD then the tests will ensure that the application is running correctly.

Of course, dynamic binding, like any other language features, is open to abuse. I fully expect to see on forums examples of people who are using it quite wrongly and getting themselves into a terrible pickle as a result. This does not mean that dynamic objects are bad, it just means programmers need to learn how to use the tools they have correctly.

Caveat Programmator: This blog post is based on early preliminary information using Visual Studio 2010 / .NET Framework 4.0 Beta 1

Software Development

Using a different map server with the Virtual Earth ASP.NET controls.

This uses the July 2008 CTP of the Windows Live tools. You can download the Windows Live Tools for Visual Studio.

One of the interesting features of Virtual Earth is that it doesn’t have to use the maps provided by Microsoft. You can set it up to point to another tile server so that you can use your own maps. This could be extremely useful for people who want to show static visualisations of data, or simply display something different to what Microsoft give you.

Setting up the tile server is likely the more difficult part as setting up the client to point at a new tile server is incredibly easy. I’m not going into setting up the tile server in this post.

First setting up the ASPX page to handle this:

<form id="form1" runat="server">
    <div>
       <asp:ScriptManager ID="ScriptManager1" runat="server"
         EnablePartialRendering="true" />
       <ve:Map ID="VEMap" runat="server" Height="600px" Width="600px"
         ZoomLevel="8" Center-Latitude="55.75" Center-Longitude="-3.5" />
    </div>
</form>

As you can see there isn’t anything unusual here. There are no additional options to set.

However, in the Page_Load event handler there are some things that need to be set up:

protected void Page_Load(object sender, EventArgs e)
{
    VEMap.DashboardSize = DashboardSize.Tiny;
    List<LatLongRectangle> bounds = CalculateBounds();
    TileSourceSpecification tileSpec = new TileSourceSpecification(
        "OSM", "", 1, bounds, 1, 18, "getTilePath", 1.0, 100, true);
    VEMap.AddTileLayer(tileSpec, true);
}
private static List<LatLongRectangle> CalculateBounds()
{
    List<LatLongRectangle> bounds = new List<LatLongRectangle>();
    LatLongRectangle box = new LatLongRectangle(
        new LatLong(90, -180), new LatLong(-90, 180));
    bounds.Add(box);
    return bounds;
}

First of all, we are reducing the dashboard side down to its minimum because the particular tile server does not support the other features provided in the dashboard such as switching between road and aerial photography.

We create the TileSourceSpecification that defines what the tile server can do and how to interact with it. The parameters are:

  • Id: An identifier for you to use to identify the tile server, if you are using more than one.
  • TileSource: You can set up a string format to define the URL of the tiles, but only if your tile server is using the same naming convention as Virtual Earth itself. It has the ability of switching between road, aerial and hybrid modes and load balancing. More info on the TileSource Property…
  • NumServers: If your tile server is load balanced then this specifies the number of servers.
  • Bounds: This is the bounding box of the tile layer. In our case above the tile server covers the entire world so our bounding box covers +90,-180 to -90,+180
  • MinZoomLevel / MaxZoomLevel: This pair of parameters specify the the minimum and maximum zoom levels. 1=the whole world, 18 = street level.
  • GetTilePath: This is the name of a javascript function that generates the path to the tile. I’ll go into more detail on that javascript function a little later on. However, if this property contains a value then the TileSource and NumServers properties are ignored.
  • Opacity: How opaque is this tile layer. By default the Virtual Earth tiles are drawn first, then your layer is drawn on top. 0 is completely transparent (and a bit pointless) while 1.0 is completely opaque and will hide the layer underneath. At present you cannot turn off the layer underneath so if you only want to see your layer set the opacity to 1.0. This is because Virtual Earth ASP.NET controls are based on Virtual Earth 6.1. 6.2 is now released which does have the ability to turn off the base layers.
  • ZIndex: Tile layers can be stacked on top of each other, this indicates the positioning of this layer in that stack.
  • Visible: Indicates whether the layer is visible or not.

In the example above the tile server does not support the virtual earth naming convention. In that case a javascript function to define the name of each tile is needed. In our example it looks like this:

function getTilePath(tileContext)
{
    return "http://tile.openstreetmap.org/" + tileContext.ZoomLevel +
         "/" + tileContext.XPos + "/" + tileContext.YPos + ".png";
}

The server for the tiles is http://tile.openstreetmap.org. If you are unfamiliar with it, Open Street Map is an open source map of the world.

The tile server refers to the individual tiles in the format “/{ZoomLevel}/{X}/{Y}.png”. These values can be obtained by the tileContext parameter (see right) passed into the javascript function.

The tile context also contains a map style property which can be “r” (road), “a” (aerial) or “h” (hybrid).

The final result looks like this:

For information about doing the same purely in javascript see this post by John O’Brien.

Software Development

Using PushPins with the Virtual Earth ASP.NET control

This uses the July 2008 CTP of the Windows Live tools. You can download the Windows Live Tools for Visual Studio.

In this post, we’re taking a look at using pushpins with the Virtual Earth ASP.NET control. We have a page similar to the previous post, with a map control on it called VEMap.

In the code behind we have a method for adding shapes to the map as this is a multi-step process. First we need to create an object to represent the point, then an object to represent the shape (we’ll come to other shape types later, but for the moment, we’re just dealing with pushpins), finally we add the shape to the map.

The Page_Load method adds a number of shapes to the map, these pushpins represent locations where Scottish Developers have held user group meetings. The code looks like this:

protected void Page_Load(object sender, EventArgs e)
{
    // Glasgow Caledonian University
    AddShape(55.8662120997906, -4.25060659646988);

    // Dundee University
    AddShape(56.4572643488646, -2.97848381102085);

    // Microsoft Edinburgh (George Street)
    AddShape(55.9525336325169, -3.20506207644939);

    // Microsoft Edinburgh (Waterloo Place)
    AddShape(55.9535374492407, -3.18680360913277);
}

private void AddShape(double latitude, double longitude)
{
    LatLongWithAltitude point = new LatLongWithAltitude(latitude, longitude);
    Shape shape = new Shape(ShapeType.Pushpin, point);
    VEMap.AddShape(shape);
}

From this we get a fairly standard output when the application is run:

At present, this is all visual. There isn’t any real functionality. What we’ll do is add some very basic functionality, so that when you hover over a pushpin it tells you something about it. The Shape object has a Description property into which you can put an HTML fragment. So, here is the updated code:

protected void Page_Load(object sender, EventArgs e)
{
    // Glasgow Caledonian University
    AddShape(55.8662120997906, -4.25060659646988,
        "<b>Glasgow Caledonian University</b>");

    // Dundee University
    AddShape(56.4572643488646, -2.97848381102085,
        "<b>Dundee University</b>");

    // Microsoft Edinburgh (George Street)
    AddShape(55.9525336325169, -3.20506207644939,
        "<b>Microsoft Edinburgh</b> (George Street)");

    // Microsoft Edinburgh (Waterloo Place)
    AddShape(55.9535374492407, -3.18680360913277,
        "<b>Microsoft Edinburgh</b> (Waterloo Place)");
}

private void AddShape(double latitude, double longitude, string description)
{
    LatLongWithAltitude point = new LatLongWithAltitude(latitude, longitude);
    Shape shape = new Shape(ShapeType.Pushpin, point);
    shape.Description = description;
    VEMap.AddShape(shape);
}

The result when you hover over a pushpin looks like this:

That’s all great if you want the default pushpin look. However, you might want to customise the pins so they match more what you are looking for. The Shape class has a CustomIcon property which you can set to be a graphics object. In the following example I’ve used a simple png file with a red circle and an semi-transparent yellow fill.

The code now looks like this:

private void AddShape(double latitude, double longitude, string description)
{
    LatLongWithAltitude point = new LatLongWithAltitude(latitude, longitude);
    Shape shape = new Shape(ShapeType.Pushpin, point);
    shape.Description = description;
    shape.CustomIcon = "images/target.png";
    VEMap.AddShape(shape);
}

And the result looks like this:

Software Development

Finding things with Virtual Earth

This uses the July 2008 CTP of the Windows Live tools. You can download the Windows Live Tools for Visual Studio.

This is a very introductory post just to show how to find things using the Virtual Earth ASP.NET control.

First you need to add an assembly reference to the Virtual Earth control to your project:

In each page that you want to use the Virtual Earth control you must add a line that looks like this at the top of the file:

<%@ Register Assembly="Microsoft.Live.ServerControls.VE"
    Namespace="Microsoft.Live.ServerControls.VE"
    TagPrefix="ve" %>

This registers the assembly allowing you to use the control.

When you view the ASPX page you will see that you have additional tools in the toolbox that relate to Virtual Earth. The one we are going to look at in this post is the Map control.

From the tool box you can drag a map control onto your design surface. The code it generates will set up a default position and zoom level which centres on the continental United States.

By default the control is a 400x400px square and has been given a name of Map1:

<ve:Map ID="Map1" runat="server" Height="400px" Width="400px" ZoomLevel="4" />

 

To start with we are going to change the defaults to something that is closer to home (well, mine at least) and centre it on central and southern Scotland and zoom in somewhat. I also don’t like the name Map1 so I’m going to change that too:

<ve:Map ID="VEMap" runat="server" Height="600px" Width="400px" ZoomLevel="8"  Center-Latitude="55.75" Center-Longitude="-3.5" />

The first thing I should comment on is the zoom level because it doesn’t really mean anything to anyone. Personally, I’d like to say “here’s a bounding box for the area I want to see, you figure out how to do that and sort out the aspect ratio for me”. Then again, maybe that’s because when I wrote a GIS system for my final year project at university that was what I did. I didn’t constrain the user to specific and artificial zoom levels. The maths behind it isn’t difficult and a modern graphics card can do that with its proverbial eyes closed. Having said that I can understand why it was done that way. It means that none of the maps are generated on the fly, it is all based on pre-existing graphic files that are retrieved as needed. This means no strained servers trying to render maps.

The zoom level ranges from 1 to 19. 1 is zoomed out to the whole world and 19 is zoomed in to street level. In between that it seems to be mostly an matter of experimentation.

As it stands the program will display a map on the page and you can zoom in or out, pan around and change display modes and so on, just like Live Maps.

Next, we’ll add some functionality to find stuff. To that end a text box (SearchTextBox) will be added in order that we can type stuff in, and a button (SearchButton) that we can submit it. The code for the button click event is as follows:

protected void SearchButton_Click(object sender, EventArgs e)
{
    VEMap.Find(string.Empty, SearchTextBox.Text);
}

The two parameters on the Find method match the two text boxes you find on Live Maps. The first parameter is the “what” (i.e. the business name or category” and the second parameter is the “where” (i.e. The address, location or landmark). If you use Live Maps a lot you’ll probably already by used to just ignoring the first box, so I haven’t included anything to populate that parameter and will just leave it empty.

Now, when the application is run the map will update when the button is clicked. It will zoom to the location you’ve specified.

At present there is no mechanism to determine where to move the map to if there is any ambiguity. For example, type “Bolton” and you’ll be taken to Bolton, England rather than Bolton, NY. Type “Washington” and you’ll be taken to the District of Columbia rather than the state. On the other hand type WA (the standard two letter abbreviation for Washington State) and you will be taken to Washington state.

The Virtual Earth control can tell you about all the places that it thought about when it was deciding where to take you. To get that we have to handle the ServerFind event on the map control. In order to do that change the ASPX markup to read:

<ve:Map ID="VEMap" runat="server" OnServerFind="VEMap_ServerFind"  Height="600px" Width="400px" ZoomLevel="8"  Center-Latitude="55.75" Center-Longitude="-3.5" />

And then add a handler in the code behind:

protected void VEMap_ServerFind(object sender, FindEventArgs e)
{
    StringBuilder sb = new StringBuilder();

    foreach (Place place in e.Places)
    {
        sb.Append("<p><strong>");
        sb.Append(place.Name);
        sb.Append("</strong> (");
        sb.Append(place.MatchCode);
        sb.Append(")<br/>");
        sb.AppendFormat("Lat: {0}, Long: {1}", place.LatLong.Latitude, place.LatLong.Longitude);
        sb.Append("</p>");
    }
    ResultLiteral.Text = sb.ToString();
}

Note: A Literal control called ResultLiteral has also been added to the page to display the results.

The ServerFind event will be raised by the map control when it finds stuff, however, you’ll notice that the page does not include the text we’ve built up. You might be thinking at this point that the event isn’t being raised at all, but put a break point down inside the code of the event. You’ll see the breakpoint is being hit.

The problem is that the ServerEvent is being handled as part of an AJAX postback rather than a page postback. If you look at the stack trace you’ll see that the map control has its own internal UpdatePanel that you would normally need to indicate that part of the page was AJAXified, so to speak. So to ensure that the code works as we would expect it to we need to add some things to the ASPX file.

First off we need a ScriptManager:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
</asp:ScriptManager>

And secondly we need an update panel of our own in order to put the controls that will be updated when the ServerFind event is handled. So the update panel, with the controls we created earlier, looks something like this.

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
    <p>
        Search:
        <asp:TextBox ID="SearchTextBox" runat="server" />
        <asp:Button ID="SearchButton" runat="server" Text="Search"
          onclick="SearchButton_Click" />
    </p>
    <p>
        <asp:Literal ID="ResultLiteral" runat="server" />
    </p>
    </ContentTemplate>
</asp:UpdatePanel>

If we search for Bolton again the results look like this:

As you can see there are several Boltons in the world.

The FindEventArgs contains many bits of information, but in the sample above we’ve just concentrated on the Place. This gives you details of the places that have been found, how good a match it thinks the place is and where the place actually is. Obviously, the more specific you are in the search the more accurate the results are going to be and the more chance you have of getting an exact match.

Note: At present there is not much documentation for the Virtual Earth ASP.NET control. Much of the functionality has been gleaned from reading the documentation for the “classic” Virtual Earth control which is customisable through Javascript. I also found a bug, which has been reported to Microsoft, that if you happen to be in Birds Eye view then the find functionality does not work.

Misc

Inserting geometry through a .NET Application

THIS POST REFERS TO THE NOVEMBER 2007 CTP (CTP 5) OF SQL SERVER 2008

Following from my previous posts (Getting started with Spatial Data in SQL Server 2008, Spatial Data in a .NET application) on the new spatial features of SQL Server 2008 I’ve been looking at how to get spatial data into SQL Server from a .NET application. This has not been as easy as expected.

I suspect I just have not found the right piece of documentation because my eventual solution isn’t one I’m entirely happy with.

I was unable to add a SqlGeometry as a parameter to the collection of parameters on the SqlCommand object in my .NET application. The SqlGeometry does not appear in the enumeration for SQL Server data types. My first thought was to put the data through as binary as I vaguely remember reading something about using binary in something I read recently, but I couldn’t quite remember where. However, when I created the geometry object in .NET then used .STAsBinary() on it so the parameter object would accept it the INSERT failed. The exception message was:

A .NET Framework error occurred during execution of user defined routine or aggregate 'geometry':
System.FormatException: One of the identified items was in an invalid format.
System.FormatException:
   at Microsoft.SqlServer.Types.GeometryData.Read(BinaryReader r)
   at Microsoft.SqlServer.Types.SqlGeometry.Read(BinaryReader r)
   at SqlGeometry::.DeserializeValidate(IntPtr , Int32 )
.
The statement has been terminated.

 

Yes, that was the MESSAGE from the exception. The stack trace above comes from within SQL Server itself. There is a separate stack track for my application. (I’m guessing if you are familiar with CLR stored procedures you may have seen this sort of thing before. I’ve not used the CLR code in SQL Server before, so it is a new experience)

The solution I found was to mark the parameter as an NVarChar, skip the creation of an SqlGeometry object and use a string containing the WKT (Well Known Text) representation. For example:

cmd.Parameters.Add("@Point", SqlDbType.NVarChar) = "POINT (312500 791500)";

I mentioned earlier that I’m not all that happy with this solution. That is because if I already have an SqlGeometry object I don’t want to have to convert it to a human readable format and have SQL Server parse it back again. Human Readable formats tend not to be the most efficient way of representing data and the geometry type already has a more efficient (as I understand it) format. Although in this case I bypassed the creation of an SqlGeometry object in my code, I can foresee cases where I might have created an SqlGeometry object through various operations and would have produced a fairly complex object. In those cases I wouldn’t want the additional overhead formatting it into WKT, passing it over the network and parsing it on the other side.

If I find a better solution I will post it.

Misc

Improving performance with parallel code

While waiting for my car to get serviced today I finally managed to catch up on reading some articles in MSDN Magazine. One of them, on optimising managed code for multi-core machines, really caught my attention.

The article was about a new technology from Microsoft called Parallel Extensions to .NET Framework 3.5 (download) which is currently released as a Community Technology Preview (CTP) at the moment. The blurb on the Microsoft site says “Parallel Extensions to the .NET Framework is a managed programming model for data parallelism, task parallelism, and coordination on parallel hardware unified by a common work scheduler.”

What I was most excited about was the ease with which it becomes possible to make an algorithm take advantage of multiple cores without all that tedious mucking about with threadpools. From what I gather the extensions are able to optimise the parallelism across the available cores. A looping construct can be set up across many cores and each thread is internally given a queue of work to do. If a thread finishes before others it can take up the slack by taking some work from another thread’s work queue.

Obviously, if an algorithm never lent itself well to parallelism in the first place these extensions won’t help much. Also the developer is still going to have to deal with concurrent access to shared resources so it is not a panacea. Those caveats aside these extensions to the .NET will make the job of using multi-core machines to their best much easier.