Archive for category Uncategorized

Integrating with third party systems using CQRS + Event Sourcing – Part 1

I’m developing a mobile application for tracking bugs called PhoneBugz. Instead of re-inventing the wheel I decided I would integrate with as many third party bug tracking systems as I could. This of course is a massive undertaking but I’ve decided to pick a few fairly popular ones and then expand from there in future versions. A major design goal of my application is a fast reliable way of logging bugs and doing bug “triage” even while disconnected from the server. In order to achieve this goal I need to make sure I can defer the work of synchronizing the server to a single operation that will happen in the background while the user continues to work. This enables scenarios where a user is offsite logging bugs they found at a customer site, and then can connect to their corporate Wi-Fi to sync the bugs once they get back to the office and synchronize with the internal bug tracking system.

This poses some major design challenges:

  • How do I ensure that changes merge seamlessly in a disconnected scenario?
  • How do I make the code flexible enough that it will work with almost any bug tracking system, especially when they have different data models?

This is where CQRS + Event Sourcing can help, at least a little. If you haven’t read up about CQRS + Event Sourcing I suggest reading some great blogs by Greg Young, Udi Dahan et al. As they will give a much more comprehensive understanding of these concepts than I ever could.

In this and other upcoming blog articles I hope to outline some of the challenges I face as I design this system and how I’ve decided upon which solution to choose.

Challenge #1: A Problem of Identity

When a bug is created on a phone that is disconnected from the “Master” server, how do you identify that bug? How do other entities in the system refer to that bug? You can’t use the master’s identity because it hasn’t been assigned yet. So you need some sort of indirection, a temporary identity if you will. One interesting technique I saw in an article by Jeremie Chassaing used strongly typed Ids for identifying aggregate roots. While this on it’s own doesn’t completely solve my problem it’s a good first step to addressing it.

Solution #1 – Mutable Identity

With this technique we have Id’s as mutable reference types where the external system’s Id is swapped under the covers when synchronizing. All referrers must refer to a single object reference for each unique Id, this way when the mapping to the external id is made, then all parties have the new information immediately. This necessitates, however, a central repository for storing Id instances in a single location, which makes storing and loading them much more difficult for other Aggregate Roots in the system.

public class MutableBugId
{
    internal MutableBugId()
    {
        this.InternalBugId = Guid.NewGuid();
    }

    public Guid InternalBugId
    {
        get; 
        private set;
    }
        
    internal int ExternalBugId
    {
        get;
        private set;
    }

    internal void MapTo(int externalBugId)
    {
        this.ExternalBugId = externalBugId;
    }
}

Pros:

  • Centralized mapping and swapping code.
  • Very simple Id class implementation.
  • Can use simple reference equality comparison for comparing id’s

Cons:

  • Have to have a central lookup of Id instances, which if static would mean that the external ids cannot be scoped without some kind of scope id e.g. if BugId’s aren’t unique across projects in the third party system.
  • Serialization of the identity by a third party becomes difficult as references must be centralized, this means that all referring parties need code serialize and de-serialize and then lookup each Id.
  • No notification that the External Id has changed, so if a component persists that ExternalId and it changes underneath them, then bugs could occur.

Using MutableBugId

Here we’ve created a simple multi-keyed repository called MutableBugIdRepository that just maintains the instances which can be looked up either by internal or external Id. The real mental gymnastics comes from storing and loading the Id’s which I’ve not listed here. Actually It’s kind of a sticking point I’m struggling to resolve.

public class MutableBugSynchronizer
{
    private MutableBugIdRepository bugIds = new MutableBugIdRepository();

    public void SaveNewBug(MutableBug bug)
    {
        var newExternalBug = this.CreateUsingWebService(bug.Summary);
        bugIds.MapBugId(bug.Id, newExternalBug.Id);
    }

    private ExternalBug CreateUsingWebService(string summary)
    {
        // TODO: Call the web service for real and get 
        // back the services version of the bug. 
        return new ExternalBug()
        {
            Id = new Random().Next(1, 10000),
            Summary = summary
        };
    }
}

Solution #2 – Immutable Identity

With this technique we use a struct that is swapped out when synchronizing with the external system, publishing an event such as BugIdReplaced when the temporary Id is swapped out with the real one. To make the code clearer I have referred to my systems BugId’s as Internal BugId’s and the third party bug tracking service id’s as External BugId’s.

public struct ImmutableBugId : IEquatable<ImmutableBugId>
{
    public static readonly ImmutableBugId Empty = new ImmutableBugId(Guid.Empty);

    private Guid id;

    private int externalId;

    private ImmutableBugId(Guid id)
    {
        this.id = id;
        this.externalId = 0;
    }

    private ImmutableBugId(int externalId)
    {
        this.id = Guid.Empty;
        this.externalId = externalId;
    }

    public static ImmutableBugId NewInternalBugId()
    {
        return new ImmutableBugId(Guid.NewGuid());
    }

    public static ImmutableBugId GetExternalBugId(int updatedExternalBugId)
    {
        return new ImmutableBugId(updatedExternalBugId);
    }

    public bool Equals(ImmutableBugId other)
    {
        if (this.externalId != 0 && other.externalId != 0)
        {
            return other.externalId.Equals(this.externalId);
        }

        return other.id.Equals(this.id);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }

        if (obj.GetType() != typeof(ImmutableBugId))
        {
            return false;
        }

        return this.Equals((ImmutableBugId)obj);
    }

    public override int GetHashCode()
    {
        return this.id.GetHashCode();
    }

    public static bool operator ==(ImmutableBugId a, ImmutableBugId b)
    {
        return a.Equals(b);
    }

    public static bool operator !=(ImmutableBugId a, ImmutableBugId b)
    {
        return !a.Equals(b);
    }
}

public class ImmutableBugIdReplaced : IDomainEvent
{
    public ImmutableBugId OldBugId { get; set; }

    public ImmutableBugId NewBugId { get; set; }
}

public class ReplaceBugIdCommand
{
    public ImmutableBugId NewBugId { get; set; }
}

Pros:

  • Clean serialization code by third parties as references instances no longer matter, as long as the current id is persisted the code will still work.
  • Id mapping code is just treated as a standard event describing a property change, that subscribers have to handle (no special plumbing code in the framework specific to mapping and replacing Ids)
  • Relying entities can decide how to handle the transition or choose to ignore the event if they don’t rely on BugIds (such as statistics report queries etc.).
  • Enables peer-to-peer synchronization without connecting to the central server as the internal Id’s remain persisted across tiers and the point at which the transition to the new id occurs is listed in the event stream.

Cons:

  • Every object that references that Id is concerned with the replacement of the Id when it’s mapped to the external system.
  • Subtle bugs could occur due to some id’s not being updated by a relying party, this includes their serialized events which would also reference those Id’s
  • Much more complicated Id types which have to support equality comparison of id’s (rather than simply using reference equality) and conversion to and from external id’s.

Using ImmutableBugId

To put it all together I’ve created a simple synchronizer class that would get called when we sync with the server. This obviously is overly simplified and doesn’t used the replayed events related to bug creation which we haven’t covered yet, but you get the idea. We perform our update on the server and then call a command to replace it’s id just like we would if we wanted to modify the Bug’s Summary field etc. The Bug (our aggregate root) then is responsible for applying this change to itself, and for publishing a BugIdReplaced event to all subscribers.

public class ImmutableBugSynchronizer
{
    public void SaveNewBug(ImmutableBug bug)
    {
        var newExternalBug = this.CreateUsingWebService(bug.Summary);
        var mappedId = ImmutableBugId.GetExternalBugId(newExternalBug.Id);
        bug.ReplaceBugId(new ReplaceBugIdCommand() { NewBugId = mappedId });
    }

    private ExternalBug CreateUsingWebService(string summary)
    {
        // TODO: Call the web service for real and get 
        // back the services version of the bug. 
        return new ExternalBug()
            {
                Id = new Random().Next(1, 10000), 
                Summary = summary
            };
    }
}

Conclusion

At the moment I am leaning towards using the immutable technique as the code does seem very clean and fits well with the Tell don’t Ask approach to object design. This design also appears to require less specialized work despite the fact that all event handling classes that refer to the BugId must now handle one more event.

Leave a comment

Delivering on the Natural User Interface Promise

The Problem with Natural User Interface Paradigm

A fair bit of talk is bubbling about this new term Natural User Interface or NUI for short. I’ve been scouring the net about this topic because I truly believe it is the future of human/computer interaction, and there are some excellent resources out there on the subject. A large part of Natural User Interfaces is multi-touch, but one thing about it has been really pissing me off: Pinch to Zoom.

Almost every time I see a demonstration of a “Natural User Interface” usually it involves multi-touch, and that inevitably reduces to the Pinch to Zoom manipulation or some variation, where by the user puts two fingers on a screen and scatters some photos around, or zooms in on a map.

Is this the best we as developers can come up with? I mean come on, this is no better than the mouse, how is raising my arm to pinch on the screen more productive than flicking my middle finger on a mouse wheel. To quote the legend Bill Buxton “something is always good for one thing, but worst for something else”. Multi-touch is crap for zooming, sorry, but there I said it, a mouse with a wheel wins for that and you probably won’t beat it. If you want to rotate a picture at the same time then fine (clicking a mouse wheel down seems to work pretty well too, but perhaps is less intuitive).

You see the temptation with the term Natural User Interface is for designers and developers to shy away from creating interactions that we has humans are unfamiliar with in our daily lives, and I don’t think that’s right. Certainly we want our applications to be easy to use, but I want multi-touch applications that are productive,, with interactions that increase the bandwidth between me and the computer, and I think I know why I haven’t seen any examples of it yet.

Most developers build using the metaphors they are familiar with, most developers don’t have the lease of time and resources to innovate and fail, they have to deliver something that’s proven to work and proven to be useful. Multi-touch will never become as ubiquitously used as the mouse and keyboard unless someone has pioneered great interactions, that have proven to be productive, and someone has made it easy for developers to incorporate it into their products. Right now there just aren’t the tools to quickly and easily make a multi-touch application beyond a scatter photo viewer.

Delivering on the NUI Promise

I’m on a mission to remedy this issue, and I don’t know if I’ll be able to do it on my own, but my plan is to develop a single application that does two things:

  1. Deliver a natural user interface that inspires developers to embrace NUI not just because it’s cool, but because it’s useful!
  2. Deliver a tool that helps developers build their own NUI applications and innovate in this space (because what I come up with may turn out to suck and that’s ok).

I’m calling this application Rush and it will be a WPF / Silverlight design and development tool (because it’s what I know). In an upcoming post I hope to journal my plans for this application, but if I’m going to deliver on this grand plan I’ll need people urging me on, so please post comments, I will need all the encouragement I can get!

Leave a comment

Quick way of checking if you’ve localised your Silverlight or WPF Xaml files

I typically use data binding to perform localisation of labels but I typically start out just by having plain text and go back later and replace these with bindings at a later stage.

e.g. <TextBlock Text=”{Binding Strings.Label_ContactDetails}” />

Here’s a really quick and easy way to make sure you’ve got your Xaml files completely localised.

1. Make sure you have downloaded LINQPad and installed it.

2. Start LINQPad and change the Language dropdown to C# Statement(s)

3. Paste this query into LINQPad and change the path to point to your project or solution folder

Code Snippet
  1. string path = @"C:\MyProjectFolder";
  2. XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;;
  3.  
  4. var attributes = new List<XName> { "Text", "Tag", "Content", "Header", "ToolTipService.ToolTip" };
  5.  
  6. var files = System.IO.Directory.GetFiles(path, "*.xaml", System.IO.SearchOption.AllDirectories);
  7. var q = from eachFile in files
  8.         let fileContent = XElement.Load(eachFile)
  9.         from eachNode in fileContent.Descendants()
  10.         from eachAttribute in eachNode.Attributes()
  11.         where attributes.Contains(eachAttribute.Name)
  12.         where !eachAttribute.Value.StartsWith("{")
  13.         select new
  14.         {
  15.             Text = eachAttribute.Value,
  16.             Node = eachNode.Name.LocalName,
  17.             Attribute = eachAttribute.Name,
  18.             FileName = eachFile.Substring(path.Length)
  19.         };
  20.  
  21. q.Dump();

 

4. Click Run and viola you have a list of all the nodes in all Xaml files that need localising!

Hope this helps!

Leave a comment

Spherical Glass Buttons in WPF and Silverlight

I long while back I post an article about Making a Glass Ball act like a Glass Button using Expression Blend and WPF. Well a reader asked me if I could share the code for these glass buttons so I’ve added a resource dictionary to my SkyDrive with the following Button templates:

image

Unfortunately this version is out of date, and I seem to have lost the original code which was more functionally complete, as you can see disabled buttons don’t fade, they used to turn to transparent glass buttons. Looking back on this my main criticism would be that the colour of the button is difficult to change, I’d have preferred if the background could be adjusted just by changing the BackColor property on a button but the gradients are just too complex to achieve this at the moment.

Hope this helps someone!

http://cid-17124d03a9a052b0.skydrive.live.com/embedicon.aspx/Public/GlassButtonResources.xaml

1 Comment

Outputting Visual Studio Logs from Silverlight Unit Test Framework

After much tearing of my hair out trying to understand how the Silverlight Unit Testing framework can output Visual Studio Test Result files (TestResults.trx), I have come up with the simplest solution I could think of, that I’m sure anyone can follow:

Setting up the Silverlight Unit Test Project

  1. Create a new Silverlight Application project in Visual Studio and add the following references:
    • Microsoft.Silverlight.Testing
    • Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight
  2. Add the following code to the Application_Startup function in App.xaml.cs:
  3. Code Snippet
    1. private void Application_Startup(object sender, StartupEventArgs e)
    2. {
    3.     var settings = UnitTestSystem.CreateDefaultSettings();
    4.     settings.TestService.UniqueTestRunIdentifier = Guid.NewGuid().ToString();
    5.     this.RootVisual = UnitTestSystem.CreateTestPage(settings);
    6. }

The Silverlight test project is now ready to have test classes added to it.

Setting up the Log Handler Web Service

The Silverlight’s Unit Testing Framework test runner has an in-built VisualStudioLogProvider that is automatically configured to output to http://localhost:8000/externalInterfaces

To support accepting the log content, you’ll need to create a special web site or Http Service to listen on this port, at this address. Stupidly this not configurable (yet), of course you could possibly implement your own logging service (and if you do I wish you luck).

The easiest way I could think of accepting the information and providing the correct responses for the TestHarness was to create an ASP.NET MVC web site.

  1. Create a new C# ASP.NET MVC web application
  2. Right click the ASP.NET MVC project, select the Web tab and change the development server to host on a specific port: 8000

    image

  3. Add a file called clientaccesspolicy.xml to the root of the web site and add the following xml to it:
  4. Code Snippet
    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <access-policy>
    3.     <cross-domain-access>
    4.         <policy>
    5.             <allow-from http-request-headers="*">
    6.                 <domain uri="*"/>
    7.             </allow-from>
    8.             <grant-to>
    9.                 <resource path="/"
    10.                           include-subpaths="true"/>
    11.             </grant-to>
    12.         </policy>
    13.     </cross-domain-access>
    14. </access-policy>

  5. Add the following code to the RegisterRoutes function in the Global.asax.cs file:
  6. Code Snippet
    1. public static void RegisterRoutes(RouteCollection routes)
    2. {
    3.     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    4.  
    5.     routes.MapRoute(
    6.         "Default",                              // Route name
    7.         "{controller}/{action}/{*pathInfo}",    // URL with parameters
    8.         new
    9.         {
    10.             controller = "Home",
    11.             action = "Index",
    12.             pathInfo = ""
    13.         }  // Parameter defaults
    14.     );
    15. }

  7. Create a new controller under the \Controllers folder called ExternalInterfacesController.cs
  8. Add the following code to the controller:
  9. Code Snippet
    1. public class ExternalInterfaceController : Controller
    2. {
    3.     [AcceptVerbs(HttpVerbs.Get)]
    4.     public ActionResult Ping()
    5.     {
    6.         return View();
    7.     }
    8.  
    9.     [AcceptVerbs(HttpVerbs.Get)]
    10.     public ActionResult GetRunParameters(string pathInfo)
    11.     {
    12.         return View();
    13.     }
    14.  
    15.     [AcceptVerbs(HttpVerbs.Get)]
    16.     public ActionResult ReportTestResults(string pathInfo)
    17.     {
    18.         return View();
    19.     }
    20.  
    21.     [ValidateInput(false)]
    22.     [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
    23.     public ActionResult SaveLogFile(string pathInfo)
    24.     {
    25.         var fileName = pathInfo.Split(‘/’).SkipWhile(part => !part.StartsWith("logName")).Skip(1).FirstOrDefault();
    26.         if (!string.IsNullOrEmpty(fileName))
    27.         {
    28.             this.Request.SaveAs(Server.MapPath(Path.Combine(@"\App_Data", fileName)), false);
    29.         }
    30.  
    31.         return View();
    32.     }
    33.  
    34.     protected override void Execute(System.Web.Routing.RequestContext requestContext)
    35.     {
    36.         // HACK: To overcome Http Form Validation (ValidateInput attribute doesn’t seem to work).
    37.         string pathInfo = requestContext.HttpContext.Request.Url.PathAndQuery;
    38.         if (pathInfo.StartsWith("/externalInterface/saveLogFile/", StringComparison.OrdinalIgnoreCase))
    39.         {
    40.             var fileName = pathInfo.Split(‘/’).SkipWhile(part => !part.StartsWith("logName")).Skip(1).FirstOrDefault();
    41.             if (!string.IsNullOrEmpty(fileName))
    42.             {
    43.                 requestContext.HttpContext.Request.SaveAs(requestContext.HttpContext.Server.MapPath(Path.Combine(@"\App_Data", fileName)), false);
    44.             }
    45.         }
    46.         else
    47.         {
    48.             base.Execute(requestContext);
    49.         }
    50.     }
    51. }

  10. Add the following Views to the Views folder (none of them should use a master page):
    • Ping.aspx
    • GetRunParameters.aspx
    • ReportTestResults.aspx
    • SaveLogFile.aspx
  11. Then replace contents of each of these views except GetRunParameters.aspx.

    Code Snippet
    1. <%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %><rsp stat="ok"/>

  12. Add the following content to GetRunParameters.aspx which tells the Silverlight Test Run the name of the computer that is running the tests.
  13. Code Snippet
    1. <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %><rsp stat="ok">
    2. <option name="ComputerName" value="<%= Environment.MachineName %>" />
    3. </rsp>

 

That’s it! Now your Silverlight Test Results will be output the the \App_Data\TestResults.trx file on the web server, the file will be replaced each time you run the tests. If you want to change the filename to something unique each time, change the SaveLogFile function accordingly.

Hope this helps!

Leave a comment

Getting Silverlight 3 Service References to work in Visual Studio 2010 Beta 2

I just downloaded and installed Visual Studio 2010 Beta 2 and decided to roll over a large Silverlight project I was working on to see how things would go.

Here are a few gotcha’s I encountered:

  1. Server side Unit Tests  were working with Membership providers but I was getting an error saying that these have been forwarded to System.Web.ApplicationServices.  What I didn’t realise is that for all the marketing guff around multi-targeting, your out of luck if you actually have unit tests in .NET 3.5, because unit tests have to be upgraded to .NET 4.  Thankfully it seems this can be easily worked around by leaving all the projects except the Unit Tests in .NET 3.5 and adding a reference to System.Web.ApplicationServices for the unit test project.
  2. Silverlight 3’s Service References were completely broken by Visual Studio in the upgrade process, so much so that I was getting errors and warnings about the service references. I think this might have had a little to do with the custom service host I had developed, but the only way I could fix it was to completely delete the Service References and then add them again, unfortunately for some reason I couldn’t use Visual Studio to delete some of the Service References. Click Delete –> nothing happens, the only way I could do it was to do this:
    1. Manually delete the service reference folder in Explorer.
      image
    2. Go to Visual Studio and exclude all the files under the service reference folder:
      image
    3. Then delete the empty folder from Visual Studio.
      image
    4. I was then free to add the Service Reference again to my Silverlight project via the Add Service Reference dialog and everything was fine.

Hope this helps someone else!

Leave a comment

Super Light Weight Multi-threaded code with ExclusiveSection

Something that has always bugged me about the .NET Base Class Library is the absence of a threading lock that would reliably tell me whether another thread was already doing something, and if so, not to block and wait for it, but just to continue on as if nothing has happened.

This becomes super useful in many multi-threaded situations, one of the main ones being User Interface threading where the foreground thread is requesting some data via an asynchronous call. Typically in this scenario, if the user makes a selection from the UI, you want the request to be sent, but if a request is already running, to ignore the user’s selection until you’re done getting the previous requests data, then at the end you can check if there was a contention and re-execute if necessary. This results in the UI remaining responsive (as in there are no locks to wait for on the foreground thread) but still ensuring the application stays in sync with the users requests.

The example I’ll give is a Windows Forms application (although it could just as easily be a WPF or Silverlight application) that searches the web and displays the html result in a textbox. I want this to be super responsive so I’ve made the application search as the user types.

Now a simple way of approximating the threading behaviour I’m after is just checking a boolean and then setting it, like so:

Code Snippet
  1.         private bool _isSearching = false;
  2.         private void SearchQueryTextBox_TextChanged(object sender, EventArgs e)
  3.         {
  4.             SearchWebAsync(SearchQueryTextBox.Text);
  5.         }
  6.         private void SearchWebAsync(string searchText)
  7.         {
  8.             if (!_isSearching)
  9.             {
  10.                 _isSearching = true;
  11.                 WebClient client = new WebClient();
  12.                 Uri searchUrl = new Uri("http://www.google.com/search?q=&quot; + searchText);
  13.                 client.DownloadStringCompleted += WebClient_DownloadStringCompleted;
  14.                 client.DownloadStringAsync(searchUrl);
  15.             }
  16.         }
  17.         private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  18.         {
  19.             if (!e.Cancelled && e.Error == null)
  20.             {
  21.                 SearchResultsTextBox.Text = e.Result;
  22.             }
  23.             _isSearching = false;
  24.         }

The problem with this code is that it can’t tell me whether the user changed their text and clicked again while the WebClient was still performing the first search and it isn’t particularly thread safe if I wanted to fire off the search from a background thread.

What’s wrong with Monitor.TryEnter?

There are a few things that have bugged me about Monitor.TryEnter, the main one being that the thread that calls Exit must be the thread that originally called TryEnter. This is all well and good in some scenarios, but in the above example it would mean I would have to call SearchWebAsync always from the UI thread. The other obvious point about Monitor.TryEnter is it doesn’t track how many times TryEnter has been attempted for a particular lock object. Not to mention it uses locking and not Interlocked statements (which are faster so I’m told although I’ve yet to see any benchmarks which say just how much faster).

Enter the ExclusiveSection class (or should I say TryEnter?)

An ExclusiveSection is used similarly to a lock in that you create an instance and then attempt to enter that section, when you do so, the ExclusiveSection.TryEnter method will return whether you were successful or not, if not you can then simply exit, knowing that the ExclusiveSection has remembered that you asked to do so.

Code Snippet
  1.     public sealed class ExclusiveSection
  2.     {
  3.         private long _entryAttempts;
  4.         /// <summary>
  5.         /// Returns true if there was more than one call to TryEnter before exiting
  6.         /// </summary>
  7.         public bool HasContention
  8.         {
  9.             get
  10.             {
  11.                 return (Interlocked.CompareExchange(ref _entryAttempts, 0, 0) > 1);
  12.             }
  13.         }
  14.         /// <summary>
  15.         /// Ensures the caller was the first to enter the Exclusive Section (Thread-safe)
  16.         /// </summary>
  17.         /// <returns>Returns True if the Exclusive Section was entered</returns>
  18.         public bool TryEnter()
  19.         {
  20.             return (Interlocked.Increment(ref _entryAttempts) == 1);
  21.         }
  22.         /// <summary>
  23.         /// Attempt to exit, useful when exits and enters are called abitrarily,
  24.         /// ensures only one exit ever succeeds.
  25.         /// </summary>
  26.         /// <returns>Returns True if the caller was the last to exit (based on the
  27.         /// number of TryEnter calls that were made)</returns>
  28.         public bool TryExit()
  29.         {
  30.             long result = Interlocked.Decrement(ref _entryAttempts);
  31.             if (result == 0)
  32.             {
  33.                 return true;
  34.             }
  35.             else if (result < 0)
  36.             {
  37.                 // Someone beat us to the punch, reset to the counter
  38.                 // to Zero to ensure we are able to enter again properly
  39.                 ExitClean();
  40.                 return false;
  41.             }
  42.             return false;
  43.         }
  44.         /// <summary>
  45.         /// Exits an Exclusive Section immediately regardless of how many calls
  46.         /// had previously been made to TryEnter and returns true if there
  47.         /// was no contention.
  48.         /// </summary>
  49.         /// <returns>Returns True if there was no more than one call to
  50.         /// TryEnter before the call to ExitClean was made</returns>
  51.         public bool ExitClean()
  52.         {
  53.             return (Interlocked.Exchange(ref _entryAttempts, 0) == 1);
  54.         }
  55.     \

The Final Result

Now I can change my code so that it uses an Exclusive Section to ensure the code only ever performs a single query at a time, and but the most recent text query entered by the user is always respected.

Code Snippet
  1.         private ExclusiveSection _searchSection = new ExclusiveSection();
  2.         private void SearchQueryTextBox_TextChanged(object sender, EventArgs e)
  3.         {
  4.             SearchWebAsync(SearchQueryTextBox.Text);
  5.         }
  6.         private void SearchWebAsync(string searchText)
  7.         {
  8.             if (_searchSection.TryEnter())
  9.             {
  10.                 WebClient client = new WebClient();
  11.                 Uri searchUrl = new Uri("http://www.google.com/search?q=&quot; + searchText);
  12.                 client.DownloadStringCompleted += WebClient_DownloadStringCompleted;
  13.                 client.DownloadStringAsync(searchUrl);
  14.             }
  15.         }
  16.         private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  17.         {
  18.             if (!e.Cancelled && e.Error == null)
  19.             {
  20.                 SearchResultsTextBox.Text = e.Result;
  21.             }
  22.             if (!_searchSection.ExitClean())
  23.             {
  24.                 SearchWebAsync(SearchQueryTextBox.Text);
  25.             }
  26.         }

Interestingly the call to SearchWebAsync can now be made from any thread, and will remain thread safe, (as long as the WebClient_DownloadStringCompleted event performed an Invoke on the UI thread to access the Windows Forms controls). This could be useful if you wanted to add a timer thread that fires off a call to refresh the search results every 30 seconds or so.

This kind of threading class is extremely useful in Silverlight where only asynchronous calls to get data are allowed.

Hope you find the ExclusiveSection class as useful as I do!

http://cid-17124d03a9a052b0.skydrive.live.com/embedrowdetail.aspx/Public/ExclusiveSectionDemo.zip

Leave a comment