Fluent.Interface


High performance Pub/Sub .NET libraries

In my search for a high-performance publish/subscribe library i again stumbled across the MS robotics CCR (Concurrency and Coordination Runtime).  The April CTP was just released an includes a number of new features including LINQ support.  The CCR remains stable and relatively unchanged, but new C# language features of lambdas and inline iterators open up new possibilities of writing streamlined async code and reduces problems with handling exceptions across threads due to the notion of Ports for success & failure scenarios.

Developers have typically steered clear of CCR given it is only bundled with MS Robotics studio (opting for alternatives such as the new TPL concurrency library), however the 200k CCR library can be shipped with your software at worst case costing US$2 per unit.

Some great examples include using CCR with ASP.NET to handle async requests showcasing iterators with yield keyword.  Another being a web crawler by Angle ‘Java’ Lopez which also leverages the DSS (decentralised software services).

An alternatives to this in-memory concurrent processing is publish/subscribe messaging over a reliable transport such as MSMQ some libraries include:

Async or concurrent programming is getting easier, and importantly more reliable.  Expect more posts and samples in the future.

Advertisements

Multi-Threading, Silverlight Sockets & Visualisation Part 3

Part 2 of this Silverlight visualisation instalment discussed how data could be streamed over a socket for rendering on the client.

To recap, Part 1 discussed how the Training Set data was loaded from file and stored in memory.  Well the data structure is as follows:

    private void SetImage(Stream stream)
    {
        BitmapImage bi = new BitmapImage();
        bi.SetSource(stream);
        this.Image1.Source = null;
        this.Image1.Source = bi;
    }
    [XmlType("T")]
    public struct TrianglePoints
    {
        public int P1 { get; set; }
        public int P2 { get; set; }
        public int P3 { get; set; }
    }

    [XmlType("P")]
    public struct TrianglePoint
    {
        public float X { get; set; }
        public float Y { get; set; }
    }

    /// <summary>
    /// A container for all the data that needs to be sent over the wire to render the image
    /// </summary>
    [XmlType("D")]
    public class TrainingSetData
    {
        public int Index { get; set; }
        public TrianglePoint[] Points { get; set; }
        public TrianglePoints[] Triangles { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
        [XmlIgnore]
        public byte[] Image { get; set; }
        public string ImageUrl { get; set; }
        public string ImageContentType { get; set; }
    }

Notice these classes have been attributed so that can be XML serialized, but that the Image blob is ignored given it is sent over as a separate block.  In addition the Socket Server that broadcasts the training set data has a configuration flag to disable streaming the image at all.  In which case the client can download the image via the specified Url.

Silverlight supports loading an image in a number of ways

1.       Relative or Absoulte Uri’s.

2.       Set directly via resource stream (loaded from memory, file etc).

3.       Downloading on demand using the asynchronous web client.

Option 1 is not appropriate given my images are dynamic and change on each request, so I have implemented Option 2 (when image is streamed over socket), and Option3 (when downloading) as the following code illustrates:

    private void RenderImage(TrainingSetData data, byte[] image)
    {
        try
        {
            if (image == null || image.Length == 0)
            {
                // Fire off a request to the web service to download the image
                if (!String.IsNullOrEmpty(data.ImageUrl))
                {
                    WebClient wc = new WebClient();
                    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(Image_OpenReadCompleted);
                    wc.OpenReadAsync(new Uri(data.ImageUrl, UriKind.Absolute), data.Index);
                    System.Diagnostics.Debug.WriteLine("Image Requested");
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("Empty Image Url");
                }
            }
            else
            {
                // Load the image setting the content type, so it knows how to read the file
                using (MemoryStream ms = new MemoryStream(image))
                {
                    StreamResourceInfo resource = new StreamResourceInfo(ms, null);
                    SetImage(resource.Stream);
                }
                System.Diagnostics.Debug.WriteLine("Image Streamed");
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("Error rendering image: " + ex);
        }
    }
    void Image_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            try
            {
                StreamResourceInfo sri = new StreamResourceInfo(e.Result as Stream, null);
                SetImage(sri.Stream);
                System.Diagnostics.Debug.WriteLine("Image downloaded");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Error downloading image: " + ex);
            }
        }
    }

The ImageUrl in this case is served up by the WCF service as configured by the Socket Service:

<appSettings>

  <add key="ModelFilename" value="..\..\..\..\data\face\models\tim_face.smd" />

  <add key="Loader.VisualisationServiceUri" value="http://localhost:1236/VisualisationService.svc" />

</appSettings>

This WCF service uses the .NET 3.5 extensions to serve up the images in a RESTful manner

    [ServiceContract]
    public interface IVisualisationService
    {
        [OperationContract]
        [WebGet(UriTemplate = "image/{index}")]
        Stream GetImage(string index);
    }

And the following implementation:

    public class VisualisationService : IVisualisationService
    {
        /// <summary>
        /// Gets the image.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public Stream GetImage(string index)
        {
            // Pull the model filename from config
            string modelFilename = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
                ConfigurationManager.AppSettings["ModelFilename"]));
            int i = Int32.Parse(index);

            // Load the training data
            VisualisationLoader loader = new VisualisationLoader();
            TrainingSetData d = loader.Read(modelFilename)[i];
            MemoryStream ms = new MemoryStream(d.Image, false);

            // Set the content type and return stream
            WebOperationContext.Current.OutgoingResponse.ContentType = d.ImageContentType;
            return ms;
        }
    }

After applying the appropriate webHttpBinding configuration, the only other consider is to include a crossdomain.xml file in the web server root, otherwise Silverlight will through a protocol error.

<?xml version="1.0"?>

<!–
http://www.mysite.com/crossdomain.xml
–>

<cross-domain-policy>

  <allow-access-from domain="*" />

</cross-domain-policy>

It is also worth pointing out that you must be running under a web project to test download of Images.  See this blog post for this and more helpful tips.

From my testing send the image stream directly over the socket resulted in better performance, but the delay in ‘downloading’ the image once the process fired up was not significant.