Asynchronous methods in C# using generics


Asynchronous methods provide a means to execute long running operations in parallel. One strategy for implementing these is to define generic methods to handle the asynchronous actions and pass the methods to be called asynchronously as parameters. A simple example follows.

The generic support methods

A class is created with static methods to support start and completion of asynchronous methods. The support methods for a single parameter with return type are shown. Other methods can be added to handle other delegate signature requirements.

    // Parameter and return type async method helper
    public static IAsyncResult BeginAsync<T1, TResult>(Func<T1, TResult> method,
                                                       T1 parameter)
    {
        var methodCopy = method;
        if (methodCopy == null)
            throw new ArgumentNullException();

        // Start the asynchronous operation
        // No callback or state object
        return methodCopy.BeginInvoke(parameter, null, null);
    }


    // Parameter and return type async method helper - async done
    public static TResult EndAsync<T1, TResult>(IAsyncResult aResult)
    {
        Func<T1, TResult> method =
            (Func<T1, TResult>) ((AsyncResult) aResult).AsyncDelegate;

        // Retrieve the result
        return method.EndInvoke(aResult);
    }

Asynchronous running

With these methods in place it becomes a simple process to use the asynchronous operations in code. Each operation calls the appropriate generic method to invoke the function, and a generic method to retrieve the result. A blocking strategy is shown here (so not applicable for use in a UI thread) but the example can easily be modified to use callbacks on completion.

    private int LongComputation(String data)
    {
        // Some long operation
        Thread.Sleep(10000);

        return data.Length;
    }

    private int MultiComputation()
    {
        IAsyncResult aRes1 =
            AsyncMethods.BeginAsync<String, int>(LongComputation, "Visions");
        IAsyncResult aRes2 =
            AsyncMethods.BeginAsync<String, int>(LongComputation, "of");
        IAsyncResult aRes3 =
            AsyncMethods.BeginAsync<String, int>(LongComputation, "Software");

        // Blocks for async call completion - not for use on UI thread
        int result = AsyncMethods.EndAsync<String, int>(aRes1);
        result += AsyncMethods.EndAsync<String, int>(aRes2);
        result += AsyncMethods.EndAsync<String, int>(aRes3);

        return result;
    }
Advertisement

WCF servers and clients without configuration files


WCF servers and clients can be set up using a declarative mechanism in web.config and app.config files. It is also possible to set up WCF servers and clients without using config files. A simple example follows.

For these examples the WCF server and client will be hosted in simple WPF applications.

WCF Server

A reference to the System.ServiceModel assembly / dll is added to link the associated namespaces. Then a ServiceContract is defined:

using System.ServiceModel;

...

[ServiceContract]
public interface IWCFContract
{
    [OperationContract]
    int Add(int value1, int value2);

    [OperationContract]
    int Multiply(int value1, int value2);
}

Next a concrete implementation of the service contract needs to be defined:

public class WCFConcrete : IWCFContract
{
    public int Add(int value1, int value2)
    {
        return (value1 + value2);
    }

    public int Multiply(int value1, int value2)
    {
        return (value1 * value2);
    }
}

Then the service host is programmatically created and the metadata is exposed and endpoints added:

using System.ServiceModel;
using System.ServiceModel.Description;

...

public ServiceHost CreateAndOpenHost()
{
    ServiceHost newHost =
        new ServiceHost(typeof(WCFConcrete),
                        new Uri("http://localhost:8002/SimpleService"));

    // Configure publication of service metadata
    ServiceMetadataBehavior behaviour = new ServiceMetadataBehavior();
    behaviour.HttpGetEnabled = true;
    behaviour.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
    newHost.Description.Behaviors.Add(behaviour);

    // Add a MEX (metadata exchange) endpoint
    newHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                               MetadataExchangeBindings.CreateMexHttpBinding(),
                               "mex");

    // Add an application endpoint using a WSHttpBinding
    newHost.AddServiceEndpoint(typeof(IWCFContract), new WSHttpBinding(), "");

    // Open the service host
    newHost.Open();

    return newHost;
}

Appropriate permissions will need to be given to the user running the application. This can be achieved by running the following in an elevated / administrator command window:

netsh http add urlacl url=http://+:8002/SimpleService user=DOMAIN\username

This service can now be run. The running service can be verified by browsing to the service in Internet Explorer:

http://localhost:8002/SimpleService

WCF Client

To create the client class run the svcutil.exe (located at C:\Program Files\Microsoft SDKs\Windows\{version}\Bin) on the wsdl for the service (while the service is running):

svcutil.exe http://localhost:8002/SimpleService?wsdl

This will create a WCFConcrete.cs (along with a config file which is not needed for this example.) This class file is added to the client project. Again a reference to the System.ServiceModel assembly will need to be added to the client project.

The ChannelFactory is then used to create a client to the service:

using System.ServiceModel;

...

public static IWCFContract CreateWCFClient(String endpointAddress)
{
    IWCFContract result = null;

    // Set up the binding and endpoint.
    WSHttpBinding binding = new WSHttpBinding();
    EndpointAddress endpoint = new EndpointAddress(endpointAddress);

    // Create a channel factory.
    ChannelFactory<IWCFContract> channelFactory =
                  new ChannelFactory<IWCFContract>(binding, endpoint);

    // Create a channel.
    result = channelFactory.CreateChannel();

    return result;
}

With this in place a client can simply be created and used to access the service (when it is running):

...

IWCFContract client = CreateWCFClient("http://localhost:8002/SimpleService");

int addResult = client.Add(2, 3);
int multiplyResult = client.Multiply(2, 3);

The adapter pattern and presenter-first UIs


The adapter pattern provides a technique to bind together the presenter logic and the UI screens of a presenter-first model (and other loosely coupled models) of user interface implementation. An example follows.

An application to double an integer requires a presenter function to perform the doubling on request:

public class Presenter
{
    public IInput Input { get; set; }
    public IOutput Output { get; set; }

    public void PerformDoubling()
    {
        int inputValue = Input.GetValue();
        int result = inputValue * 2;
        Output.SetValue(result);
    }
}

The presenter is using interfaces to access the user interface – which allows presenter unit tests to be built via mocks independent to the development of the UI:

public interface IInput
{
    int GetValue();
}

public interface IOutput
{
    void SetValue(int newValue);
}

Binding the interfaces to a deployed UI can then take the form of UI-specific adapters to the IInput and IOutput interfaces. I.e. for a Window1 class containing input and output accessors (implemented using explicit marshalling as described in this blog entry):

public partial class Window1 : Window
{
    ...

    public String ThreadSafeGetInputValue() ...
    public void ThreadSafeSetOutputValue(String newValue) ...
}

The following two adapters can be used to convert the UI to match the required interface without the need to modify the UI code. (Null and error checking has been excluded below to reduce code footprint:)

public class AdapterIInputWindow1 : IInput
{
    private Window1 Window1 { get; set; }

    public AdapterIInputWindow1(Window1 wrappedWindow)
    {
        Window1 = wrappedWindow;
    }

    // IInput implementation - excluding error checking
    public int GetValue()
    {
        int result = Convert.ToInt32(Window1.ThreadSafeGetInputValue());
        return result;
    }
}


public class AdapterIOutputWindow1 : IOutput
{
    private Window1 Window1 { get; set; }

    public AdapterIOutputWindow1(Window1 wrappedWindow)
    {
        Window1 = wrappedWindow;
    }

    // IOutput implementation - excluding error checking
    public void SetValue(int newValue)
    {
        Window1.ThreadSafeSetOutputValue(newValue.ToString());
    }
}

Finally the UI can initialize its presenter and set the IInput and IOutput interfaces to the appropriate adapters:

public partial class Window1 : Window
{
    private Presenter Presenter { get; set; }

    public Window1()
    {
        InitializeComponent();

        Presenter = new Presenter();
        Presenter.Input = new AdapterIInputWindow1(this);
        Presenter.Output = new AdapterIOutputWindow1(this);
    }


    public void XamlAction(object sender, EventArgs args)
    {
        Presenter.PerformDoubling();
    }
    ...
}

Use explicit marshalling to update a WPF UI from a non-UI thread


One option for updating a WPF UI from a non-UI thread (including a background worker) is to perform explicit marshalling using the dispatcher. A simple example follows.

A separate blog entry details how to update a UI using a background worker’s implicit marshalling.

Lets assume there is a C# window mediator class that has a reference to a pair of WPF controls – one for user input and one for user reporting. The WPF window constructs the mediator and sets the two control properties during its construction. Two functions provide access to the data and may be called from any thread:

public partial class MainWindow : Window
{
    private WindowMediator m_mediator = null;

    public MainWindow()
    {
        InitializeComponent();
   
        m_mediator = new WindowMediator();

        // Controls declared in the window's XAML
        m_mediator.IncomingDataControl = m_xamlTextBox;
        m_mediator.ReportDataControl = m_xamlTextBlock;
        ...
    }
    ...
}

public class WindowMediator
{
    // Controls.  A TextBox to retrieve data and a TextBlock to report data
    public TextBox IncomingDataControl { private get; set; }
    public TextBlock ReportDataControl { private get; set; }

    // Access functions to retrieve and set data (also see below)
    public String GetIncomingData(bool reformat) { ... }
    public void SetReportData(String newReport) { ... }
}

When updating the values of a WPF control, the code needs to be executed on the UI thread – i.e. the thread that owns the WPF control. The control’s dispatcher provides a function CheckAccess (which is the equivalent of the Windows Forms property InvokeRequired) to determine whether the call is currently executing on the UI thread.

If not – the Invoke method of the dispatcher can be used to execute a delegate on the appropriate thread. The Action framework class can be used to generate a Delegate from the current method (or from an anonymous method) and pass the parameters across:

public void SetReportData(String newReport)
{
    if (!ReportDataControl.Dispatcher.CheckAccess())
    {
       // Switch threads and recurse
       ReportDataControl.Dispatcher.Invoke(
          System.Windows.Threading.DispatcherPriority.Normal,
          new Action<String>(SetReportData), newReport);
    }
    else
    {
        ReportDataControl.Text = newReport;
    }
}

A similar method can be used to retrieve data from a WPF control. The generic framework class Func can be used to add a return type:

public String GetIncomingData(bool reformat)
{
    String result = "";

    if (!IncomingDataControl.Dispatcher.CheckAccess())
    {
       // Switch threads and recurse
       result = (String) IncomingDataControl.Dispatcher.Invoke(
          System.Windows.Threading.DispatcherPriority.Normal,
          new Func<bool, String>(GetIncomingData), reformat);
    }
    else
    {
        if (reformat)
        {
             result = "--" + IncomingDataControl.Text;
        }
        else
        {
             result = IncomingDataControl.Text;
        }
    }

    return result;
}

Covariance and contravariance in C# 4.0


C# 4.0 introduces covariance and contravariance (together variance) for generic type parameters. These two concepts are similar and allow the use of derived or base classes in a class hierarchy.

An easy way to understand the difference between the two concepts is to consider the activity of the user of the variables passed to / from the generic method (interface or delegate.)

Contravariance

If the method implementation is only using variables passed with the parameter for read activity – then the generic parameter is a candidate for contravariance. The ‘read only’ role of the parameter type can be formalised by marking it with the in keyword – i.e. it is an input to the implementation.

Any generic type parameter marked with the in keyword will be able to match to types that are derived from the named type. In this case the implementation is the user of the variables. It makes sense to allow derived classes as any read activities that are available on the base class will also be available on any derived class.

// C# 3.0 does not recognise the in keyword for parameterized types
public delegate void TypeReporter<in T>(T input);

public void DoSomeGenericContravariance(RoutedEventArgs args)
{
    TypeReporter<EventArgs> ReportMethod
                  = new TypeReporter<EventArgs>(this.SimpleReportMethod);

    // C# 3.0 and earlier will not compile the following
    TypeReporter<RoutedEventArgs> RoutedReportMethod = ReportMethod;

    RoutedReportMethod(args);
}

public void SimpleReportMethod(EventArgs args)
{
    Console.WriteLine(args.GetType().ToString());
}

Covariance

Similarly – if a method implementation is only using variables passed with the parameter for write activity – then the generic parameter is a candidate for covariance. The ‘write only’ role of the parameter type can be formalised by marking it with the out keyword – i.e. it is an output from the implementation.

Any generic type parameter marked with the out keyword will be able to match to types that are base classes of the named type. In this case the calling / client code can be considered the user of the variables – so again it makes sense. Any operation (read or write) that is available on the base class that the client code has requested will also be available on the actual (derived) type that the implementation instantiates / sends as output.

public void DoSomeGenericCovariance()
{
    // The generic IEnumerable interface is defined with the out keyword
    // on the parameter type:
    //
    // public interface IEnumerable<out T> : IEnumerable

    List<String> strings = new List<String> { "one", "two" };
    IEnumerable<String> myStrings = strings.AsEnumerable();

    // C#3.0 and earlier will not compile the following
    IEnumerable<object> myObjects = myStrings;

    foreach (object myObject in myObjects)
    {
        Console.WriteLine(myObject.ToString());
    }
}

Issues to consider

Once type parameters have been marked with the in or out keyword the compiler will validate the interface / delegate compliance with the assigned variance. E.g. if the first example is changed to return the parameter passed, then the compiler will report an error – as the parameter is not being used for input only.

// Compiler will report a variance validation error
public delegate T TypeReporter<in T>(T input);

Variance uses reference type conversion – so it will not work with value types. Even though within the type system int inherits from object, the following will not compile.

List<int> ints = new List<int> { 1, 2 };
IEnumerable<int> myInts = ints.AsEnumerable();

// Reference type conversion not available
IEnumerable<object> myIntObjects = myInts;

C# and NUnit – testing interface implementations


A common development strategy is to generate interface definitions and then code against these – allowing the implementations to be varied easily.

When writing NUnit test cases for interfaces and implementing classes – it is possible to generate a set of test cases for the interface and then apply these test cases to each concrete implementation. A strategy is outlined below.

Within the class library containing the test cases generate a test fixture for the interface itself. A class member, m_fileManager in this case, is used to hold the interface instance to test and a second member m_runTests is used to track whether the fixture holds an interface realisation.

A virtual function CreateConcrete is defined to create the concrete interface implementation – it is called in the SetUp method.

Add the interface test cases to this class – checking whether tests should by run using the m_runTests member.

[TestFixture]
public class Test_IFileManager
{

    /// Interface to use for testing
    protected IFileManager m_fileManager;

    /// Indicator that we are in a realisation test fixture
    protected bool m_runTests = false;

    /// Create a concrete instance
    virtual public void CreateConcrete()
    {
    }
        
    [SetUp]
    /// Test set up
    public void Setup()
    {
        CreateConcrete();
    }

    [TearDown]
    /// Test tear down
    public void TearDown()
    {
        m_fileManager = null;
        m_runTests = false;
    }

    [Test]
    /// A simple test
    public void NonExistentDirectoryThrowsException()
    {
        if (m_runTests)
        {
            Console.WriteLine("Running test: NonExistentDirectoryThrowsException");

            Assert.Throws<DirectoryNotFoundException>
                ( delegate
                  {
                    m_fileManager.GetFreeFileName(@"ZZ:\BadDrive\", "stem", "txt");
                  });
        }
    }
}

To attach the set of test cases to a concrete implementation, generate a class that inherits this base interface testing class. Override the CreateConcrete method to assign the interface instance and to indicate that the tests should be run.

[TestFixture]
public class Test_IFileManager_SimpleFileManager : Test_IFileManager
{

    /// Create a concrete instance
    override public void CreateConcrete()
    {
        // Using static method
        m_fileManager = (IFileManager) SimpleFileManager.GetFileManager();
        m_runTests = true;
    }

}

Each implementing class can be tested by creating a separate concrete implementation testing class. When NUnit runs it finds all of the interface tests and runs them for each concrete implementation.

If any implementation-specific test cases exist, then they can be added to the concrete testing class. If a class implements multiple interfaces, then each interface can be tested in a similar manner by generating a concrete implementation testing class for each interface / implementer pair.

Optional parameters and named parameters in C#4.0


If you are familiar with C++ or VB then you will already be familiar with optional parameters. They are parameters that are assigned a default value at compile time and that can be omitted when calling a method.

  public void LayoutElements(IList<Element> elements, int xOrig = 0, int yOrig = 0)
  {
    ...
  }
  
    ...

    layoutTool.LayoutElements(elementList);         // Will layout at 0, 0
    layoutTool.LayoutElements(elementList, 25, 25)  // Will layout at 25, 25

C#4.0 adds the ability to define optional parameters for methods, constructors and indexers.

An obvious area of use is constructors. Optional parameters remove the need to define multiple overloaded constructors with a variety of parameters all calling into a single constructor which does the work.

Any optional parameters must be declared after all non-optional parameters. You can overload a method to have two versions – one with an optional parameter and one without. In this case the compiler will resolve to the method without the optional parameter (following the principal of least surprise.)

    
  public void LayoutElements(IList<Element> elements)
  {
     LayoutElements(elements, 5, 5);
     ...
  }

  public void LayoutElements(IList<Element> elements, int xOrig = 0, int yOrig = 0)
  {
    ...
  }

    ...

    // Resolves to first method - will layout at 5, 5
    layoutTool.LayoutElements(elementList);

Another addition, named parameters, helps when calling a method, constructor or indexer. Similar in function to named parameters used with attributes.

You use the name of the variable to fill the parameter – using a colon to specify the value.

  // Will layout at 0, 10
  layoutTool.LayoutElements(elementList, yOrig: 10);

Named parameters can be used for both optional and positional parameters. When making the function call all named parameters must occur after any positional parameters. The named parameters do not have to appear in the order of the parameters in the method declaration.

  // Will layout at 15, 10
  layoutTool.LayoutElements(yOrig: 10, xOrig: 15, elements: elementList);

If you use partial methods, then for both optional and named parameters the declaration in the definition is used at compile time.

  partial void LayoutElements(IList<Element> elements, int xOrig = 0, int yOrig = 0);

   ...

  partial void LayoutElements(IList<Element> elements, int x = 5, int y = 5)
  {
    ...
  }

    ...

//    layoutTool.LayoutElements(elementList, y : 10);    // Will not compile
    layoutTool.LayoutElements(elementList, yOrig : 10);  // Will layout at 0, 10

Be aware that if you rename parameters in a method that is called elsewhere with the named parameter syntax, then the names will no longer match and the calling code will not compile.

Update UI from background worker thread without explicit marshalling


It is possible to update the UI thread from a background worker thread without the need to explicitly marshal the call across to the UI thread. An example follows.

A separate blog entry details how to update a UI using explicit marshalling.

The background worker member is used to perform potentially long lasting non-UI activities:

    private BackgroundWorker m_bw = new BackgroundWorker();

When starting the background worker (e.g. in the instance constructor after InitializeComponents for a WPF application) set the flag to indicate that the worker reports progress and add a ProgressChangedEventHandler:

    m_bw.DoWork += bw_DoWork;
    m_bw.WorkerReportsProgress = true;
    m_bw.ProgressChanged += bw_ProgressChanged;
    m_bw.RunWorkerAsync();

In the background worker activity when you want to update the UI call the ProgressChanged method on the background worker using the overload to pass a state object:

    int progress = 50;
    var state = new KeyValuePair<string, string>("Status", "Still working");
    m_bw.ReportProgress(progress, state);

The event that this call raises is raised on the thread that created the background worker – so in this case the UI thread – which means that implicit marshalling has occurred. In the ReportProgressEventHandler you can then directly update the UI controls:

    void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        ...

        var state = (KeyValuePair<string, string>) e.UserState;
        m_xamlProgress.Text = e.ProgressPercentage + "%";
        m_xamlStatus.Text = "Status: " + state.Value;

        ...
    }

This approach separates the creation of the update data from the activity of updating the controls – providing an implicit interface between the worker thread and the UI thread.

In more complex scenarios where threads that have not been created by the UI thread need to update controls the mechanism of Control.InvokeRequired followed by use of Invoke / Dispatcher can be used.

Spring clean your usings


If you have worked on software that has been extended, upgraded and re-factored over time – then you will be aware that using statements accumulate at the top of C# files.  Some of these will be for namespaces and types that are no longer used in the code below.

An addition to the Visual Studio 2008 IDE is the ability to clean up and organise these using statements.

Just right-click to get the context menu in your code files and you will see the new menu option “Organize Usings”.  With this you can remove usings that are no longer in use, or sort the usings for a more aesthetic list.  Or why not go for a full clean up and do both!