Saturday, 23 March 2013

C# syntactic sugar - the lock statement

Inspired by a talk I saw a DevWeek 2013 by Andrew Clymer, I took a look at the IL created by the C# compiler when the lock keyword is used. If you don't need an introduction to how the lock statement works, scroll down a bit and skip the first couple of C# snippets.

The Lock Statement

As a brief introduction to the lock keyword, it is used as a mechanism to allow access by a thread to a critical piece of code. Typically, this is when you have the possibility of multiple threads trampling on each other's data.

Take the sample code here:
using System;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
    public static void Main(string[] args)
    {
        // Create a totaliser
        var totaliser = new Totaliser();

        // Set it off on a new thread
        Task.Run(() => totaliser.ModifyTotal());

        // Give the totaliser a chance to do something
        Thread.Sleep(100);

        // Write the current total
        Console.WriteLine(string.Format("Current value of Total: {0}", totaliser.Total));
        Console.ReadLine();
    }
}

public class Totaliser
{
    public int Total { get; private set; }

    // increment the total to 500, then down again to 0
    public void ModifyTotal()
    {
        for (var counter = 0; counter < 5000000; ++counter)
        {
            Total++;
        }
        for (var counter = 0; counter < 5000000; ++counter)
        {
            Total--;
        }
    }
}
The intent of the Totaliser class is to be able to freely increment and decrement its Total without any external visibility of what's happening. Unfortunately, because its Total property is publicly readable, the Total can be read at any stage in the increment-decrement cycle in a multi-threaded environment:

A solution to this problem is to use the lock statement, around the reads and writes to Total:
using System;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
    public static void Main(string[] args)
    {
        // Create a totaliser
        var totaliser = new Totaliser();

        // Set it off on a new thread
        Task.Run(() => totaliser.ModifyTotal());

        // Give the totaliser a chance to do something
        Thread.Sleep(100);

        // Write the current total
        Console.WriteLine(string.Format("Current value of Total: {0}", totaliser.Total));
        Console.ReadLine();
    }
}

public class Totaliser
{
    private object lockObject = new object();

    private int _total;
    public int Total
    {
        get
        {
            lock (lockObject)
            {
                return _total;
            }
        }
        private set { _total = value; }
    }

    // increment the total to 500, then down again to 0
    public void ModifyTotal()
    {
        lock (lockObject)
        {
            for (var counter = 0; counter < 5000000; ++counter)
            {
                Total++;
            }
            for (var counter = 0; counter < 5000000; ++counter)
            {
                Total--;
            }
        }
    }
}
See the new lockObject at line 26, and the lock statement at lines 33 and 44.

The lock statement forces the thread to obtain a lock on the lockObject before it can proceed; if another thread has the lock, it must wait until it's been released. The result is a success:

The IL

Looking at the IL produced by the compiler, you can see the framework objects used to implement the lock:

.method public hidebysig specialname instance int32 
        get_Total() cil managed
{
  // Code size       48 (0x30)
  .maxstack  2
  .locals init ([0] bool '<>s__LockTaken0',
           [1] int32 CS$1$0000,
           [2] object CS$2$0001,
           [3] bool CS$4$0002)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  .try
  {
    IL_0003:  ldarg.0
    IL_0004:  ldfld      object Totaliser::lockObject
    IL_0009:  dup
    IL_000a:  stloc.2
    IL_000b:  ldloca.s   '<>s__LockTaken0'
    IL_000d:  call       void [mscorlib]System.Threading.Monitor::Enter(object, bool&)
    IL_0012:  nop
    IL_0013:  nop
    IL_0014:  ldarg.0
    IL_0015:  ldfld      int32 Totaliser::_total
    IL_001a:  stloc.1
    IL_001b:  leave.s    IL_002d
  }  // end .try
  finally
  {
    IL_001d:  ldloc.0
    IL_001e:  ldc.i4.0
    IL_001f:  ceq
    IL_0021:  stloc.3
    IL_0022:  ldloc.3
    IL_0023:  brtrue.s   IL_002c
    IL_0025:  ldloc.2
    IL_0026:  call       void [mscorlib]System.Threading.Monitor::Exit(object)
    IL_002b:  nop
    IL_002c:  endfinally
  }  // end handler
  IL_002d:  nop
  IL_002e:  ldloc.1
  IL_002f:  ret
} // end of method Totaliser::get_Total


System.Threading.Monitor

Does that mean we could use the System.Threading.Monitor class to manually implement our own lock? Yes, of course. A simple C# lock statement such as
        lock (lockObject)
        {
            DoSomething();
        }
actually gets compiled as if the C# statements were
        object obj = (System.Object)lockObject;
        System.Threading.Monitor.Enter(obj);
        try
        {
            DoSomething();
        }
        finally
        {
            System.Threading.Monitor.Exit(obj);
        }
The System.Threading.Monitor class has a couple of options when trying to grab a lock on an object, in particular the TryEnter method. This has an overload that takes a timeout value in milliseconds, which specifies how long this thread should wait to obtain the lock
        object obj = (System.Object)lockObject;
        if (System.Threading.Monitor.TryEnter(obj, 3))
        {
            try
            {
                //Do something
            }
            finally
            {
                System.Threading.Monitor.Exit(obj);
            }
        }
        else
        {
            //Do something else
        }
I don't advocate rewriting your lock statements to use the longhand versions above, but this hopefully removes a layer of abstraction between you and your multi-threaded executable.

Monday, 28 January 2013

Use the Dictionary Indexer for upserts


If you have a Dictionary<T,T> and you want to upsert a value (i.e. update or insert depending on its existence), you don't have to perform the existence check yourself:

It turns out the dictionary's set indexer will do the check for you. All you need is

This applies to the .Net Dictionary<T,T>, SortedDictionary<T,T> and SortedList<T,T> implementations of IDictionary<T,T> .  But bear in mind that if you're coding to the abstraction IDictionary<T,T>, you can't guarantee that the specific implementation you're using will work this way.

Saturday, 5 January 2013

Pick A Ship-It-Day Project That Scares You

Our team has started running Ship It Days (a short write-up here) as a way of driving innovation for the company. The basic idea is that the whole development team gets 2 days to work on small projects, each of which will either deliver a feature for the company or increase the technical knowledge within the team.

As an example, over 2 days this week, we [a team of 2 developers and 2 testers] produced a heatmap of phone calls in progress on our network, across the world. We produced code to surface phone call data, map the source and destination phone number prefixes to geographic points, and overlay the routes on Google Maps' world map. The map is likely to be displayed in the Network Operations Centre as a dashboard item to see how busy the network is, and by customers to see what calls are in progress on their contact centre.

Although the 2 days were an absolute success in terms of delivering the feature (it won 2 company-wide votes, Best Minimum Viable Product and Most Innovative), for me the work involved was too close to my day job for me to get *really* excited. Don't get me wrong; I love the job I do and could think of few jobs I'd rather do than write code all day. But. This project was about surfacing, transforming and visualising data, using WebAPI, C# and JavaScript.

Next time, I'll choose a project that scares me.

Friday, 7 December 2012

Suppress the Visual Studio splash screen

If you start Visual Studio and it shows this:
You can suppress it by adding /nosplash to the command line in the shortcut used to launch Visual Studio:




Voilá!

Saturday, 24 November 2012

SignalR Demo In Pictures

Disclaimer: this demo is not intended to show best practice in C#, javascript, HTML, MVC, Visual Studio, NuGet etc etc. It is intended to use as a picture-book style guide to creating RPC communications between a web client and an ASP.Net application using SignalR.
Note: the code is not as simple as I'd hoped, but it changed to use a singleton to hold the timer, after the lack of best practice with a SignalR hub was pointed out by one of its authors.























Wednesday, 10 October 2012

Caller Information Attributes

Version 4.5 of the .Net framework introduces 3 new attributes in the System.Runtime.Compiler namespace. These are CallerFilePathAttribute, CallerLineNumberAttribute and CallerMemberNameAttribute. They are used to obtain information about the caller to a method, and are handy for tracing call flow for diagnostics. The CallerMemberNameAttribute is also particularly useful when calling a PropertyChanged method, if your class implements INotifyPropertyChanged.

A quick code example shows the usage ( all code here is available as a GitHub:Gist)
The output from this demo is:
The new attributes are at lines 20, 21 and 22 of the code. As you can see in the example, to use one of the attributes, it must be used to decorate an optional parameter on a method - the parameter will be set to the correct value at runtime.

INotifyPropertyChanged Usage

One major benefit of the CallerMemberNameAttribute is in a class that implements the INotifyPropertyChanged interface. This interface has an event in the form of PropertyChanged(string propertyName), and will be called from each property's setter method when the value changes. This leads to a lot of magic strings in code, for example:
This brittle code can be avoided by using the attribute like this:

What members does it work with?

As well as methods, properties and events, the attributes will work for these member types:
  • Constructor, value is ".ctor
  • Explicit conversion operator, value is "op_Explicit"
  • Implicit conversion operator, value is "op_Implicit"
  • Indexer, value is "Item"
  • Operator overload, value is e.g. "op_Addition"
  • Finaliser, value is "Finalize"

Where does the info come from?

The attributes work by inspecting the IL of the calling code. For instance, the IL for the Main() method of my first example contains these items of info:

As I said before, all code here is available as a GitHub:Gist

Monday, 1 October 2012

Simple Breakpoint Options in VS2012

When you create a breakpoint in Visual Studio 2012, you have certain options available that determine exactly when the debugger breaks and what happens when it does. These options are available via the Breakpoints window (Debug -> Windows -> Breakpoints, or Alt+F9)...

...or by right-clicking the breakpoint:
I'll go through the first few of these menu options and describe its use.

Delete Breakpoint

No surprises here; selecting this menu item has the same effect as hitting F9. It deletes the breakpoint.

Disable Breakpoint

This option disables the breakpoint, so Visual Studio won't break at this breakpoint until it is enabled.

Location...

This shows a window that allows the code location of the breakpoint to be edited:
This is useful if e.g. you have multiple code statements on the same line; it allows you to set a breakpoint on a specific statement, by selecting the character position of a character in the required statement (note, this can also be achieved by selecting the statement and hitting F9) :
The screen gives the option to Allow the source code to be different from the original version. When this option is selected, if the source file of a debugged library has changed from the version referenced, the debugger will still allow the referenced version to be debugged.

Condition...

This shows a window that allows you to change the condition that must be satisfied before the debugger stops the code at the breakpoint:
The condition can be set to Is true, i.e. when the condition is met, or Has changed, i.e. when the specified variable or expression evaluates to a new value.
The example above sets the breakpoint to break when the variable loopCounter is equal to 719 0r 725:

Hit Count...

This shows a window that allow you to specify the number of times the breakpoint needs to be hit before the debugger breaks:
The default for a breakpoint is for it to break every time the statement is reached. Other options allow you to specify a numeric value that is used to calculate whether the debugger should break:
This example causes the debugger to break when the statement has been hit 183 times:
While the debugger is paused at the breakpoint, opening the Hit Count window shows the current hit count, and allows you to reset it so that the count starts again from zero.