Oct 202012
 

Intro

Long before Microsoft .NET 4.5 was a reality, in the days when asynch programming was not a given, I developed a bit of a concurrency wrapper implementation which has been used on a variety of projects.

At the threat of being redundant (in light of the across-the-board support for Asynch in .NET 4.5) I’ve decided to write up my old threading approach in the hopes that it might be useful to those not yet using .NET 4.5.

This implementation isn’t terribly advanced, I just thought it might be useful for someone “out there”.  It’s not been exhaustively tested or reviewed, so please be kind to it.  As usual, the normal conditions apply

A case in work packages

What I wanted, about two years ago, was to quit writing the same thread synchronization logic over and over again.  It seemed that whenever I wanted to repeat a series of tasks using threading, I was caught using a lock synch and some kind of support for marshalling events to a UI.

Finally sick of implementing roughly the same implementation or design over and over again, I sat down and figured out what I’d want from an API perspective – something I could throw different objects, types, handlers and events at and produce some semblance of consistency using multiple threads.

Design work

What I wanted to do was write a wrapper on top of the .NET Framework’s threading implementation (System.Threading) and using the Framework’s own queuing implementation, i.e.

ThreadPool.QueueUserWorkItem(ThreadProc, package);

The design took into account a number of different usage scenarios, for example “light weight” usage (simple setup and execute) versus more complex requirements like an ability to signal abort a single thread or using a master abort signal to terminate all running threads.

As this was originally designed to work with Windows services, the logic needed the ability to respond to a shutdown event, so threads had to respond to out of band requests within a reasonable time.  As work load could also chop and change, the ability to enqueue new work was added later.

Class Warfare

So the basic design derives from a ThreadPoolManager (which co-ordinates thread execution and packaging) and a ThreadWorkPackage which is what the work to be performed is “wrapped” in.  The Manager class is given either a set of packages, or a single package which constitutes the work to be performed.

image

The real magic is in the establishment of the work packages (providing proc locations for the work to be performed) and the arguments used in beginning execution.  There are a number of considerations to be made before executing threads.

Full disclosure: there are a number of classes in a common assembly which really come from a larger and more complex “enterprise” solution which I designed and built in 2010, so these are somewhat just stubs or placeholders at this time.  To keep the solution to a minimum, I removed A LOT of the original implementation.

image

Advantages

So what the ThreadManager class really allows you to do it to leverage some “boiler plate” implementation which handles setting up your event callbacks, thread counters, synchronization objects and setting (and triggering) any event abort signals you’d care to use.

Probably one of the best ways to demonstrate this is in some code samples which show how you’d take advantage of the ThreadManager.

An easy example below shows how to do a “minimal fuss” configuration, noting that the bulk of the configuration is in setting up the configuration of each individual ThreadWorkPackage.

[TestMethod]
public void TestSynchExecution()
{
    List<ThreadWorkPackage> packages = TestCommon.GetWorkList("Basic Test", 40, 0, new ThreadWorkPackage.ExecutionEvent(callback));
    ThreadPoolManager mgr = new ThreadPoolManager();
    mgr.BeginExecution(packages, true);
}

 

public static List<ThreadWorkPackage> GetWorkList(string jobTitle, int itemsToAdd, int multiplier, ThreadWorkPackage.ExecutionEvent callbackEvent)
{
    List<ThreadWorkPackage> items = new List<ThreadWorkPackage>();

    for (int x = 0; x < itemsToAdd; ++x)
    {
        ThreadWorkPackage package = new ThreadWorkPackage();
        package.PackageId = (x + 1) + multiplier;
        package.PackageSeries = jobTitle;
        package.PackageProcessingEvent += callbackEvent;         items.Add(package);
    }
    return items;
}


As you can see, limited code is needed to get something simple up and running.  Let’s have a look at the operation which is being invoked in the ThreadManager class:


/// <summary> 
/// Used for Wait Signal-free Calls 
/// </summary> 
/// <param name="workItems">[Required] A collection of items to execute</param> 
/// <param name="synchronous">[Required] Whether or not to wait until they have completed</param> public void BeginExecution(List<ThreadWorkPackage> workItems, bool synchronous)
{
    BeginExecution(workItems, synchronous, false, null, String.Empty, -1);
}


This simply calls another overloaded operation which eventually drives to the following, which actually invokes work package (and thread) execution:

Now that’s a whole lot of arguments!  Here are the rest of th


/// <summary> 
/// Start Processing as a batch 
/// </summary> 
/// <param name="workItems">[Required] A collection of items to execute</param> 
/// <param name="synchronous">[Required] Whether or not to wait until they have completed</param> 
/// <param name="ignoreExecution">[Required] Whether to execute or not, if another set of items are currently being executed 
/// Note that ignoring executing threads will delay triggering of the Finished Processing event, as it increments the total count of threads 
/// </param> 
/// <param name="masterSeries">[Optional] A master abort handle, to abort all packages at once</param> 
/// <param name="masterWait">[Optional] A common descriptor - required when using a master abort signal</param> 
/// <param name="timeOut">[Optional] When to timeout from thread execution - used with master abort</param> 
/// <param name="maxWorkerThreads">[Optional] Max Worker Threads</param> 
/// <param name="maxCompletionPortThreads">[Optional] Max Completion Port Threads</param> 
/// <exception cref="NotSupportedException"> 
/// Only one execution batch is supported at any one time. 
/// Wait for the current execution to finish first. 
/// </exception> 
/// <exception cref="InvalidOperationException"> 
/// The arguments passed to BeginExecution must not be null and must contain at least one valid item 
/// </exception> 
/// <exception cref="NotSupportedException"> 
/// We use the masterSeries string to determine which threads to trigger an abort for, which is why it is a required field 
/// when a master wait handle is used for aborting package threads 
/// </exception> public void BeginExecution(List<ThreadWorkPackage> workItems, bool synchronous, bool ignoreExecution, AutoResetEvent masterWait, string masterSeries, int timeOut, int maxWorkerThreads, int maxCompletionPortThreads);

e possible arguments of the overloaded BeginExecution functions:

image

Event Driven

What you might have noticed in the definition of the ThreadManager is that it’s entirely configurable whether you want to be notified when one or all threads have finished executing.  Events are available and can be used to help you determine when work has completed – or was interrupted:

#region Events

/// <summary> /// Called when all Threads have finished executing /// </summary> public delegate void FinishedProcessing();
public event FinishedProcessing FinishProcessingEvent;

/// <summary> /// Called when an individual thread has finished executing /// </summary> protected delegate void ThreadFinished();
protected event ThreadFinished ThreadExecutionFinished;

/// <summary> /// Called when a thread has been aborted /// </summary> protected delegate void ThreadAborted();
protected event ThreadAborted ThreadExecutionAborted;

#endregion 


You might also have noticed that the individual ThreadWorkPackage class instances can have events too – for when the thread executes successfully, or when the thread is aborted:

public delegate void ExecutionEvent(ThreadWorkPackage package);
public event ExecutionEvent PackageProcessingEvent;

public delegate void ExecutionAbortEvent(ThreadWorkPackage package, bool timeOut);
public event ExecutionAbortEvent PackageAbortEvent;

You might note the timeOut boolean parameter – the package can be set a timeout value if execution doesn’t complete within a specified time.  This value will indicate whether a thread was aborted due to the abort signal being raised, or due to an execution timeout.

Synchronous Execution vs. Asynchronous

Another advantage is that you can kick off execution of work packages without having to wait for all the threads to finish.  Using the events, you can just be notified when work completes, or if there are any unexpected errors.

Conversely, you can just as easily kick off execution and have the ThreadManager not return until work is completed.

Unit Tests

There are a few unit tests, but there were a plethora more in my original solution.  I’ve republished some within the sample solution, however I’d recommend writing some of your own if you plan to have a play with the solution.  It’ll help you understand the implementation better.

imageimageimage

More Options

The manager class has quite a number of additional options , including the ability to limit the max number of worker threads, and to “throw some more work” onto the list of threads to be executed.  It’s probably worth playing around with a few different options to see if this is suitable for your needs.

Known Issues

There’s one thing I’m aware of which I haven’t had time to correct, and probably quite a few more.

One issue is that the abort signals registered by ThreadPool.RegisterWaitForSingleObject are not properly unregistered when processing finishes.

When execution is finished, any abort events which were registered should be unregistered using RegisteredWaitHandle.Unregister(..).  Sorry about that, I got a tad bit slack when I was putting this together, it’s an oversight I’d like to correct.

Feedback

Please be kind.  With the birth of our first child earlier this year, I haven’t had nearly as much time as I usually would to either write this article or review the sample code/solution.

I’ve had this code running in a “production-like” environment underpinning Windows services which are running 24/7 without too many problems, but that doesn’t mean it’s bug free by any stretch of the imagination.

If you see any problems or encounter any issues, please drop me an email at rob.sanders@gmail.com.  I’d love to factor in feedback, modifications etc.

Source Code

Source Code ThreadManager.zip

Sep 142012
 

Casablanca is a Microsoft incubation effort to support cloud-based client-server communication in native code using a modern asynchronous C++ API design. Think of it as Node.js, but using C++. Casablanca gives you the power to use existing native C++ libraries and code to do awesome things on the server. Come and watch John Azariah and Mahesh Krishnan show you how it is done”

Presented by John Azariah and Mahesh Krishnan

Disclaimer: These are conference session notes I compiled during various sessions at Microsoft Tech Ed 2012, September 11-14, 2012.  The majority of the content comprises notes taken from the presentation slides accompanied, occasionally, by my own narration.  Some of the content may be free hand style.  Enjoy… Rob

Arrived about ten minutes late due to delays in checking out of the hotel.  John’s now in the process of compiling and running a Hello World sample.

The Node Influence on Casablanca

  • Asynchronous, non-blocking I/O
  • Powerful libraries (many external modules)
  • Simplicity

Sample Node.js approach to a hello world HTTP response looks very similar in C++.
The http namespace used in C++ is out of Casablanca.

Node.js sample:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

..and a C++ Casablanca version:

http_listener listener = 
        http_listener::create("http://localhost/path_1",
            [](http_request request)
            {
                request.reply(status_codes::OK, "Hello, World!");
            });
    listener.open();

Some Inclusions:

  • Web
    • RESTful services
    • JSON
  • The Cloud
    • SDK for accessing Azure storage

[Demo] Serializing JSON, implementing a RESTful interface and hooking to Azure

  • Mapping HTTP verbs to actions, e.g.
    • Read = GET,
    • Update = PUT,
    • Insert = POST,
    • Delete = DELETE

Possibly using the following syntax:

MyListener::MyListener(const http::uri& url) :
        m_listener(http_listener::create(url))
    {
        m_listener.support(methods::GET,
                           std::tr1::bind(&MyListener::handle_get,
                                          this,
                                          std::tr1::placeholders::_1));
        m_listener.support(methods::PUT,
                           std::tr1::bind(&MyListener::handle_put,
                                          this,
                                          std::tr1::placeholders::_1));
        m_listener.support(methods::POST,
                           std::tr1::bind(&MyListener::handle_post,
                                          this,
                                          std::tr1::placeholders::_1));
        m_listener.support(methods::DEL,
                           std::tr1::bind(&MyListener::handle_delete,
                                          this,
                                          std::tr1::placeholders::_1));
    }

Demonstration of all of the above shows that JSON serialization in/out is quite seamless (at this stage).

IMG_2309 IMG_2310
Handling JSON & Using Cloud Storage

C++ Specific Advantages

[Demo] Text to Speech Demo

Wow, I haven’t seen some of those pre-processor and #pragma statements in a long time. 

[Demo] PhotoSynth Web Service

Photosynth has a web service implementation now.  Uploading multiple photos and getting back the panorama is quite cool.

Here’s the panorama taken at the session.

IMG_2313 

Casablanca Task Libraries

IMG_2314

[Demo] Mandelblot example rendered from locally via Casablanca.

IMG_2315 IMG_2316

The next big thing coming out of the Casablanca Team is GPU processing.

Summary

  • Casablanca is an incubation effort
  • Allows you to write end-to-end Azure apps in C++
  • If you are already programming in C++ you can migrate your apps to Azure
Aug 082011
 

Now for something completely different.  Recently I had the desire to build a Visual Studio 2010 solution file for a number of project files under a directory.  There were many projects, and each one linked to a solution file – but I wanted a “master” solution file.. one to rule them all(?)

Generally, I hate manual repetitious tasks, and laboriously adding all the projects to a  new, blank, solution file seemed tedious and not fun one bit.  Then I decided that I’d write a program which would iterate all the projects and create a solution file for me.  Sounds simple enough, right?

Well, it took me on a journey into Visual Studio automation.  There are many facets of working with VS, as I found out, and backwards compatibility reigns supreme.  What I’m going to introduce you to is pretty much just for Visual Studio 2010, but in the right hands a design could come which supports versions dating back to Visual Studio 2005.

The Prerequisites

Optional Extras

Once you’ve got your system all nicely configured, we’re ready to begin.

The Beginning

To begin with, I created a Class Library.  My intention was to create a large amount of nice, reusable automation for integration into Team Build, utilities and so forth.  You never know when this is going to be very, very handy.

To start our journey, I decided that my requirement was going to be very simple (for Part 1): create a blank solution file using Visual Studio 2010.  Easy enough, right?  Well, as you’d expect, the devil is in the details.  This took me quite a bit of time to get right, but in the end the outcome was most pleasing.

So open up Visual Studio, create a project type you’d prefer and then ready the project, as so:

  1. Add a reference
  2. Pick the COM tab
  3. Scroll and select “Microsoft Development Environment 10.0”
  4. This will add several COM interop assemblies to your project (and also include the previous versions)
  5. Click on the .Net tab and select “Microsoft.VisualBasic” (even if you aren’t coding in Visual Basic)

image image

Now it is time to go code us up a simple solution.  I’m going to be working on a far more robust library, but in the meantime this will introduce you to the extremely powerful DTE and DTE2 objects.

We have to (sadly) instantiate a COM object wrapper, which will actually load devenv in a non-interactive mode, from which we can then cherry pick functionality we’d like to use.  For this demo, we’re just going to create a Visual Studio 2010 compatible solution file.

Consider the following very simple class:

namespace VSAutomation.Toolkit
{
    public static class SolutionHelper
    {
        public static void CreateSolution(string path, string solutionName)
        {
            DTE2 dte2 = (DTE2)Microsoft.VisualBasic.Interaction.CreateObject("VisualStudio.DTE.10.0", "");
            Solution4 solutionObject = (Solution4)dte2.Solution;
            solutionObject.Create(path, solutionName);
            solutionObject.Close(true);
        }
    }
}

You will notice that we create a COM object instance using the VisualBasic namespace.  When the code actually creates the object, under the hood, the machine will see an instance of Visual Studio created (but no GUI):

image

Once it is loaded, we can get access to the VS Solution functionality.  From here, it is a simple matter of supplying the path and solution name (omit the .sln extension) and, assuming all goes to plan, you will have the following output:

image

Obviously this is just the tip of the iceberg. 

We have so much powerful functionality to exploit, so we won’t stop at this.  Since we’ve achieved our objective for Part 1, we’ll wrap up here, but check back for Part 2 where we’ll populate the solution file with existing (or new) projects!

In the next part, we’ll also discuss ways of supporting the older versions (Visual Studio 2008 and 2005) as well as providing a more verbose sample.


Further Reading

How to: Get References to the DTE and DTE2 Objects

Solution4.Create Method (String, String)