iMeta Consultancy Services

Syndication

Blog Stats

  • Blogs - 75
  • Posts - 620
  • Articles - 0
  • Comments - 1174
  • Trackbacks - 2907

Bloggers (posts, last update)

Latest Posts

The Task Parallel Library Series - The Task Class

Now that we understand the principles of Task Parallelism, let's see how to do it in .Net 4. In previous versions of .Net, there were two main options. One was to launch a new thread for each task:


var thread = new Thread(() =>
	{
		DoSomeWorkHere();
	});

thread.Start();

DoOtherWork();
DoOtherWork();
DoOtherWork();

thread.Join();

Console.WriteLine("All work completed");	

The other was to make use of the built-in thread pool1:


ThreadPool.QueueUserWorkItem(_ =>
	{
		DoSomeWorkHere();
	});

DoOtherWork();
DoOtherWork();
DoOtherWork();

Console.WriteLine("My work completed.");
Console.WriteLine("No idea what the threadpool task is doing.");

Which of these was best? Well, it largely depends on what you are doing. If you have some long-running task2 to execute then launching a new thread is probably a reasonable way forward; although threads are relatively expensive objects, the cost is amortised over the life of the task which, for big tasks, makes the overhead pretty much irrelevant. It also leaves the thread pool (which has a limited number of threads) available for doing what it does best, which is the execution of relatively small tasks.

In general, the thread pool tended to be the option that most people went for; long running tasks are not that common (remember that the longest sequential chain limits how fast your code can ever run, so long running tasks are best avoided), and the thread pool offered a good combination of ease of use and performance.

However, to do anything more than a "fire & forget" approach with the thread pool is problematic. Once you call QueueUserWorkItem, you essential loose contact with the work that you've just submitted. To keep in touch, you need to hand roll the code yourself (usually involving some combination one of more ManualResetEvent or Monitor objects). Why would you need to keep in touch? Well, if the tasks is performing some form of calculation or gathering data from some external service, you'd probably quite like to access the result. Sure, it can stick that in some member field of a class that is shared with the calling code, but you still need to know when the processing is complete before you attempt to access the field. (Hmm, shared stuff again. Wasn't that bad or something?).

Plus, what if your processing throws an exception? You need to handle that, otherwise it's game over for the whole process3. So you need to have a mechanism for communicating these events back to the "main" thread. And how about cancellation? What if a user initiates some task that could take some time, and then changes her mind? Ideally, you'd like to cancel that task to save on the unnecessary processing. Again, here come those volatile flags, events etc. to let you perform such synchronisation.

This is all pretty unsatisfactory. There's an awful lot of plumbing that needs to be written when using either the thread pool or regular threads, and this code obscures the logic that you're trying to express (you know, the stuff the customer is paying for. They typically don't give a damn about all this threading stuff). Plus it tends to end up relatively complex and hard to reason with, which makes the creation and/or introduction of bugs more likely.

So, this post is all about .Net 4 and yet all I've done so far is moan about the previous state of affairs. Let's see some new code:


var task = Task.Factory.StartNew(() =>
	{
		return DoSomeWorkHere();
	});

DoOtherWork();
DoOtherWork();
DoOtherWork();

task.Wait();

Console.WriteLine("All work completed. Task returned {0}", task.Result);

Simple stuff to start with (future posts will expand much further), but this code starts a Task and then proceeds to do some other work. At a later point, it waits on the task and gets back the result. You'll note the total absence of anything to do with threading - no locks, no events, nothing. You'll also note that there's no shared state - the Task does it's work and returns the results - no messing about with shared fields and the associated synchronisation.

So what are the Task and the Factory types? You can think of Task as a representation of some value (the result) which will be available at some point in the future, and it provides suitable members for waiting on and accessing the result once execution completes. The Factory provides the abstraction over the mechanism by which the task is scheduled & executed - is it in the thread pool, does it run on some specific thread (maybe the UI thread, for example) or is it some async call that doesn't actually have a thread permanently associated with it? The default factory (as used above) simply delegates to the thread pool (but with all the plumbing that's needed to make it useful) but that can be overridden, which we'll look at in a future post

So, that hopefully gives you an easy introduction to the Task class. Future posts will drill into more depth on usage scenarios, covering many of the things that were problematic prior to .Net 4.0.


1BTW, what's with that odd "_" in the lambda for QueueUserWorkItem? Well, the delegate that it expecting is a WaitCallback, which is defined as public delegate void WaitCallback(object state);. From that, you can see that any method being used as the start of a thread has a state argument. In our lambda, we don't make use of this, and the convention is to use "_" as the name for an unused argument in a lambda. "_" is a perfectly valid C# identifier, so there's no magic here. Of course, if you have more than one argument that is unused, you can't use "_" for both of them!

2By long running task, I mean some continuous "thread" of execution within a program. Clearly there are many examples of long running business tasks that can lasts many hours (or days or weeks), but this behaviour is typically implemented through some state that is persisted and "resumed" at the appropriate points. Trying to model a business process by running a single thread that starts when the business process starts and just keeps running until the business process has finished is unlikely to be a great solution :)

3By default (and quite correctly, IMO), the .Net runtime will abort any process that has an unhandled exception on any thread. This was a change made in, if I recall, .Net 2.0 - prior to that, it was only unhandled exceptions on the main thread that caused the process to abort. On other threads the thread would just silently die, leaving the application running but now in some (by definition) undefined state. I don't know about you, but hoping that code is going to execute properly when the application state is undefined doesn't sound like the best idea in the world.

posted @ 8/30/2010 1:31 PM by Steve Strong

JQuery and OData

A common model enabling a web application to search a remote source for data could be as follows.

The HTTP POST method allows the data set of an HTML form to be sent to a processing agent, typically a web server.  The web server is responsible for querying a remote data source, typically a database.  This can be achieved using a variety of techniques, such as old-fashioned ADO.Net in the ASP.Net page code behind or by more up-to-date ORM technologies.  The web server will use the result of the data source query to re-render the HTML page and send it back to the browser.

There are several steps here making the model more complicated than it might need to be.  Why do we need to POST to the web server?  After all, is it not essentially acting as an intermediary between the browser and the data source?  Is it possible to remove the web server from this model?

WCF Data Services and the Open Data Protocol (OData) combined with JQuery make it possible to remove the web server from our web application searching a remote data source scenario.  If you are unfamiliar with WCF Data Services and OData there is plenty of material elsewhere that I won’t attempt to regurgitate here, http://msdn.microsoft.com/en-us/data/aa937697.aspx is a good primer, OData itself has a comprehensive site at http://www.odata.org/.

That’s the introduction finished with, let’s look at an example using the Netflix OData service (http://developer.netflix.com/docs/oData_Catalog).

Code Snippet
  1. $(document).ready(function() {
  2.  
  3.     $("#searchForm").submit(function() {
  4.  
  5.         $.ajax({
  6.             url: "http://odata.netflix.com/Catalog/Titles?$top=10&$callback=ajaxCallback&$format=json",
  7.             dataType: "jsonp",
  8.             success: ajaxCallback,
  9.             jsonpCallback: "ajaxCallback"
  10.         });
  11.  
  12.         return false;
  13.     });
  14.  
  15.     function ajaxCallback(result) {
  16.  
  17.         $("#results").empty();
  18.         for (var i = 0; i < result.d.length; i++) {
  19.             $("#results").append("<strong>Name:</strong> " + result.d[i].ShortName + "<br/>");
  20.             $("#results").append('<strong>Genres: </strong> <a href="' + result.d[i].Genres.__deferred.uri + '">here...</a><br/>');
  21.             $("#results").append("<strong>DateModified:</strong> " + result.d[i].DateModified + "<br/>");
  22.             $("#results").append("<strong>Type:</strong> " + result.d[i].Type + "<br/>");
  23.             $("#results").append("<strong>Synopsis:</strong> " + result.d[i].Synopsis + "<br/><br/>");
  24.         }
  25.     }
  26.  
  27. });

 

Here I’ve set up a very basic page containing a form to search with and an empty div to display the results in.  Using JQuery to hook into the submission of the form I’ve set up a fairly standard ajax call that will get the top 10 Titles from the Netflix catalogue.  Because the Netflix OData service is on a different domain to my script I need to use JSONP to call it.  This is where the added url complexity comes from, if the service was on the same domain as my script the url would be much simpler (e.g. “http://odata.netflix.com/Catalog/Titles?$top=10&$format=json”) and we would not need to specify the jsonpCallback parameter.  I specify a success callback function to do something with the JSON result, I simply spit out a few properties to screen in the results div – but it’s easy to imagine more funky examples! Finally I return false to prevent the standard form submission from occurring.

If you look into the OData protocol you will notice that there are many many things that can make up the url:- $filter, $orderby, $skip, $expand, $select and $inlinecount come to mind in addition to the possibility of calling service operations.  This makes handcrafting the url potentially complex and time consuming.

After a quick bit of research I discovered a small OData plugin that already exists for JQuery - http://wiki.github.com/egil/jquery.odata/.  It removes the need to handcraft the urls – replacing them with more intuitive function calls – as well as hiding the potentially nasty ajax call setup.

Code Snippet
  1. $(document).ready(function() {
  2.  
  3.     $("#searchForm").submit(function() {
  4.  
  5.         $.odata("http://odata.netflix.com/Catalog/", { dataType: 'jsonp' })
  6.             .from("Titles")
  7.             .top(10)
  8.             .query(odataCallback);
  9.  
  10.         return false;
  11.     });
  12.  
  13.     function odataCallback(result) {
  14.  
  15.         $("#results").empty();
  16.         for (var i = 0; i < result.data.length; i++) {
  17.             $("#results").append("<strong>Name:</strong> " + result.data[i].ShortName + "<br/>");
  18.             $("#results").append('<strong>Genres: </strong> <a href="' + result.data[i].Genres.__deferred.uri + '">here...</a><br/>');
  19.             $("#results").append("<strong>DateModified:</strong> " + result.data[i].DateModified + "<br/>");
  20.             $("#results").append("<strong>Type:</strong> " + result.data[i].Type + "<br/>");
  21.             $("#results").append("<strong>Synopsis:</strong> " + result.data[i].Synopsis + "<br/><br/>");
  22.         }
  23.     };
  24.  
  25. });
  

JQuery.OData makes it much easier to work with OData services but still allows you pass through many options as per normal JQuery plugin patterns, above I pass through a dataType property set to JSONP to be used in the ajax call.  The success callback is pretty much identical, JQuery.OData does wrap up result.d into a more friendly result.data.

We’re currently using this plugin in a project at iMeta and have been pleased with it so far.  If you find yourself with the need call an OData service and don’t want to perform full page postbacks, I thoroughly recommend giving JQuery.OData a go! 

If you’re unfortunate enough to be supporting IE6 then give me a ping as I’ve spent many an hour so far debugging it and had to make a couple of tweaks to get JQuery.OData to play nice with it.

Other than that, the Fiddler web debugging tool is your friend when working with OData services, studying the request and response headers has proved to be a vital skill.

posted @ 8/26/2010 11:53 PM by Mike Godfrey

Speeding up Visual Studio Build Times and Performance

 

Our product solution build times have been getting progressively slower as more assemblies and features have been added.

We did the following:

  • Made all our build output go to one folder, main assemblies to one folder, test assemblies to another. This made about a 5x performance improvement as VS didn’t need create copies of dependent assemblies for each assembly built.
  • Split solution into component area’s and just reference Assemblies. This allows us to run VS with only a few projects, with a limited number of projects VS is now usable. Although this doesn’t improve the overall build time it significantly improves component build times when only developing within one component area.

 

This following points are important when trying to achieve the above:

  • Re-sharpers navigate to command helps here as you can navigate to the assemblies source code found from the symbol files directly.
  • All build output goes to $(solutionroot)/bin and $(solutionroot)/testbin regardless of the configuration, so different configurations still work when using an assembly reference.
  • The automated build process references each different solution via the SolutionToBuild item group, so we don’t need to maintain assemblies in more than one solution, i.e. there isn’t one solution that builds everything.
  • The Team build agent does search its own output folders for dependent assemblies, so you don’t need to copy them from the team build output to the location other assemblies are referencing them from.
  • When you have multiple solutions with dependencies between them it appears you cannot perform a parallel build, at least the team build agent cannot. I added the <BuildSolutionsInParallel>false</BuildSolutionsInParallel> property to the property section of the team build .proj file which disabled this behaviour allowing the solutions to be build in the correct order. Interestingly I had upgraded my machine to run a the RC of VS 2010 which appears to have altered the team build targets file (its different to the VS 2008 sp1 build file present on the build boxes), when I locally built the team build project with the /m switch passed to msbuild for parallel builds it succeeded.
  • Other advantages include keeping assembly dependencies from creeping over their component boundaries, i.e. if a solution only contains assemblies for one component area you can’t accidentally add references to assemblies outside that component area.
  • Splitting the solution up has a massive speed improvement when using VS, i.e. going from un-usable to usable.

posted @ 8/23/2010 4:26 AM by James Allderidge

Installing VS2008 SP1 breaks Team Build Agent

 

I installed VS 2008 SP1 on our build box running a TFS 2008 Build agent which broke the build process. Every build failed with the following error:

C:\Program Files\MSBuild\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets(300,15): error MSB4131: The "Reason" parameter is not supported by the "GetBuildProperties" task. Verify the parameter exists on the task, and it is a gettable public instance property.

In installing the SP1 update the team build targets had been updated at “Program Files\MSBuild\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets” but the team build tasks assembly used by team build agent wasn’t updated so there was a mismatch between the .

The task assembly location is “\Program Files\TeamBuildServiceFromTFS2008\Common7\IDE\PrivateAssemblies\Microsoft.TeamFoundation.Build.Tasks.dll", i.e. the TFS build client install. The VS 2008 SP1 has updated the team build targets file but not the team build agents assemblies (its updated a copy of the same task, in the VS installation instead)

To get the team build agent working again I had to install the TFS server SP1 which can be downloaded from:

http://www.microsoft.com/downloads/details.aspx?familyid=9e40a5b6-da41-43a2-a06d-3cee196bfe3d&displaylang=en

 

 

posted @ 8/23/2010 3:21 AM by James Allderidge

ASP.NET Web Service and Integrated Windows Authentication only working with IP address

 

We have an issue on a customer deployment where our web service can only be accessed when communicating using the IP address in the URL rather than the host name. We are using integrated windows authentication to pass the users windows credentials so we can automatically log the user into our application. The application itself is a windows form app using dot net 2 web proxies to access asp.net web services.

In our environment accessing the services using a host name is fine but in the clients environment accessing via the host name fails, but IP address access succeeds. In short it appears the issue surrounds the interplay between Kerberos and NTLM authentication. The main reason our test environment is different to the clients environment is that they run the web services as a specific domain user and not NETWORK_SERVICE, when you do this Kerberos will not work out of the box.

In short the following links show how the clients deployment environment can be changed to work with domain names when not running the app pool as network service, either by turning of Kerberos authentication off, or by fixing it properly using Service Principle Names (SPNs)

Essentially NTLM is always used when communicating via an IP address (Wikipedia NTLM), this would explain why accessing the web service via an IP address works.

To change the authentication and to turn NTLM and Kerberos authentication on.

http://support.microsoft.com/kb/215383

To turn it off and the reason why:

http://piers7.blogspot.com/2007/04/disable-kerberos-on-windows-2003-using.html

Fixing by using a SPN

http://support.microsoft.com/?id=929650

Investigation in our environment

The following text records the investigation in our test environment surrounding the asp.net web service running as a domain user or NETWORK_SERVICE account.

The domain controller sees a logon event when talking to a web service not using network service as a user, but this doesn’t show any issue, in general I didn’t see an events in the domain controllers security logs that show the issue:

image

There are no logon events when communicating to a web service using network service.

The Application server has the authentication methods set to: “Send LM & NTLM – user NTLMv2 session security if negotiated” was ''Send NTLM response only on our test environment”. Potentially its what the setting is set in the client that counts here, this has no effect on choosing between Kerberos and NTLM though.

Communicating to the IP address;

No clients can connect to the web service when using the IP address for some reason, the exact opposite of the clients environment. Potentially NTLM is broken for us and Kerberos is the only thing that is working, our test environment is running in a VM environment with its own DC and network, the client and app servers though are also connected to our main network to make RDP easy, potentially this is causing issues and definitely an area to investigate.

Coms Traffic

DNS Name, Network Service

Response 401

WWW-Authenticate: Negotiate

WWW-Authenticate: NTLM

 

Request

Authorization: Negotiate YIIE0QYGKwYBBQUCoIIExTCCBMGgJDAiBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICCqKCBJcEggSTYIIEjwYJKoZIhvcSAQICAQBuggR+MIIEeqADAgEFoQMCAQ6iBwMFACAAAACjggOpYYIDpTCCA6GgAwIBBaEKGwhDUzAyLkNPTaIlMCOgAwIBAqEcMBobBEhUVFAbEmNzMDJhcHAwMS5DUzAyLmNvbaOCA2UwggNhoAMCARehAwIBDKKCA1MEggNP4AAuMFXJKP79YjQoyhaQKaG5Iwmmk8dFvKK/gb+78ZYUZRkZ42S+gNrfETPNJhufN2CGFwyJ9PIBmk0Ra7FIkZrJPLPHcBN97M46O1VOQtJdYYX0XvpdgrjEtuCobGAI43gKEMfGBaSZ1lt5Pi7xpNo1xN76/pgq+4vJvQ+SnOGPLgTRk/lSoVXyX3zJ5UJSmROSsAD46RU6eIQ+pNR8+NjZvd5sclQ8P/L/y62UKFcWKZA2ppVghIrQd1kmvgfip4EdR1/Apf+rT8gvgqxPuSHhfdL/kaQRWjY0dvdCKlxszytF2HQN1wYl/6ECezfeuejwtljVfSjzuAsnhjE2aESJpmXohoTiPD1HD8Hsa6Je8y7WLHyh8+DVoVJzLXPBRg/FxPxrsq1YL/KOJnx9+y9sPwUwMci621Fd571Me+I531YOCPMEQG0APOZR7zGTQRaWMQN602zsh9AKeFcUhcAvDHBPvHzeQ7m5YeOUHNIEH3lrnD8NV5UOqHePZunsHLV9aiehaUtT6rrpjOvVQ1tuvopwph7UE/PStfjLDeG1ClHWlTo8vKdYVaL1w7ktnwhifw/oqd4AiChwe6NIcuFAnvTG1eWoUPcVMHnknPSk6tmclYqn3iDKqnfw52VNoE1f8aRldCWm4hqgnUPbA6+5Z7oWzBy7sxsqE3xaJcsIxeOeeplcEyF7MYQfwo0D5RofHEN2qU+MG/oMCDpMm6zyK7HJXIiAEJh81rb53c9MdAl9aC8X/oUF2x36ntau2KUmm35Wt0QCL5qpjLdMFqYowWzQkogoVykBNUPVeYaaFdYpx/uuRMhWgM9k+8YridLAs+UX4ToJ456Zszk88UiUV7bIQU5LZGg9UDnBQzXSequLcUqD87CVhZb0tTzT7R6JRW9gkkij5tvMCBt8ab4xhhzOz++jPnmLJMSlOwujCNKgD3B0gzMlVHafDJmG3OBbVg3wuXLX5CDqJ4hZh1kpku2bj4mQvD1ZD+Bo+XTkrUCx4gCZAGr/vgizCjQDt4hEz83/9sD+FQP7Phwcfzx3AkWyg01Tb22n8KcF5bg/oy6I30t0eOr/llHtf/spc6PYVY5BZyIqsC7wv9RWaJfPvoTt/MYuni7wlL5zdaSBtzCBtKADAgEXooGsBIGpWy0v1ywq0PMWh3Q6HdKAgMZq4HJASGqCT+Ccg4wIRNnlVYsoEz822J0DdcB3qaxXIX1NcOKIR5Xcds9yJGOR1imL8YHCJX3DsMGqfs4XUBVzF5Y+SGG43/XL7++ERITTbSFzTpwsS82EylwvOEyyAyC96golat9VSJTy3fbzisgGpZn+M4wGeiCOdJz7bS38Xhl+jPkKZpQtb0wDG1juJf4QvSAXFrzPUA==

 

Response 200

WWW-Authenticate: Negotiate oYGgMIGdoAMKAQChCwYJKoZIgvcSAQICooGIBIGFYIGCBgkqhkiG9xIBAgICAG9zMHGgAwIBBaEDAgEPomUwY6ADAgEXolwEWoZdDKSN9Xs6Da1N/G/a/wB0aW1V47bz9OpCwXBnHxTx0tPGrxhI7474Nbg1zaLrIJvOorUSE/q010CuG0t0xYoHIbkirCFcK6LrQgAkXIuyEgkvrTJ+Rl+TBg==

No logon events

 

IP Address, Network Service

Response 401

WWW-Authenticate: Negotiate

WWW-Authenticate: NTLM

 

Request –> 401

Authorization: Negotiate TlRMTVNTUAABAAAAt4II4gAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw==

Response

WWW-Authenticate: Negotiate TlRMTVNTUAACAAAACAAIADgAAAA1gonihXsqEfDBUGoAAAAAAAAAAHYAdgBAAAAABQLODgAAAA9DAFMAMAAyAAIACABDAFMAMAAyAAEAEgBDAFMAMAAyAEEAUABQADAAMQAEABAAQwBTADAAMgAuAGMAbwBtAAMAJABjAHMAMAAyAGEAcABwADAAMQAuAEMAUwAwADIALgBjAG8AbQAFABAAQwBTADAAMgAuAGMAbwBtAAAAAAA=

 

Request –> 401

Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAHYAAAAYABgAjgAAAAgACABIAAAADAAMAFAAAAAaABoAXAAAABAAEACmAAAANYKI4gUBKAoAAAAPQwBTADAAMgBhAGQAbQBpAG4AMQBDAFMAMAAyAEQARQBTAEsAVABPAFAAMAAxAA7a339UA42oAAAAAAAAAAAAAAAAAAAAAAn8jU3tc3kILSb0cqGJjoiOlOdOcU8Le9CGQnUdqskW6W9Z5Fd4R5g=

Response

WWW-Authenticate: Negotiate

WWW-Authenticate: NTLM

 

Similar requests when not using network service, the second is a 401 with

Request

Authorization: Negotiate YIIE0QYGKwYBBQUCoIIExTCCBMGgJDAiBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICCqKCBJcEggSTYIIEjwYJKoZIhvcSAQICAQBuggR+MIIEeqADAgEFoQMCAQ6iBwMFACAAAACjggOpYYIDpTCCA6GgAwIBBaEKGwhDUzAyLkNPTaIlMCOgAwIBAqEcMBobBEhUVFAbEmNzMDJhcHAwMS5DUzAyLmNvbaOCA2UwggNhoAMCARehAwIBDKKCA1MEggNP4AAuMFXJKP79YjQoyhaQKaG5Iwmmk8dFvKK/gb+78ZYUZRkZ42S+gNrfETPNJhufN2CGFwyJ9PIBmk0Ra7FIkZrJPLPHcBN97M46O1VOQtJdYYX0XvpdgrjEtuCobGAI43gKEMfGBaSZ1lt5Pi7xpNo1xN76/pgq+4vJvQ+SnOGPLgTRk/lSoVXyX3zJ5UJSmROSsAD46RU6eIQ+pNR8+NjZvd5sclQ8P/L/y62UKFcWKZA2ppVghIrQd1kmvgfip4EdR1/Apf+rT8gvgqxPuSHhfdL/kaQRWjY0dvdCKlxszytF2HQN1wYl/6ECezfeuejwtljVfSjzuAsnhjE2aESJpmXohoTiPD1HD8Hsa6Je8y7WLHyh8+DVoVJzLXPBRg/FxPxrsq1YL/KOJnx9+y9sPwUwMci621Fd571Me+I531YOCPMEQG0APOZR7zGTQRaWMQN602zsh9AKeFcUhcAvDHBPvHzeQ7m5YeOUHNIEH3lrnD8NV5UOqHePZunsHLV9aiehaUtT6rrpjOvVQ1tuvopwph7UE/PStfjLDeG1ClHWlTo8vKdYVaL1w7ktnwhifw/oqd4AiChwe6NIcuFAnvTG1eWoUPcVMHnknPSk6tmclYqn3iDKqnfw52VNoE1f8aRldCWm4hqgnUPbA6+5Z7oWzBy7sxsqE3xaJcsIxeOeeplcEyF7MYQfwo0D5RofHEN2qU+MG/oMCDpMm6zyK7HJXIiAEJh81rb53c9MdAl9aC8X/oUF2x36ntau2KUmm35Wt0QCL5qpjLdMFqYowWzQkogoVykBNUPVeYaaFdYpx/uuRMhWgM9k+8YridLAs+UX4ToJ456Zszk88UiUV7bIQU5LZGg9UDnBQzXSequLcUqD87CVhZb0tTzT7R6JRW9gkkij5tvMCBt8ab4xhhzOz++jPnmLJMSlOwujCNKgD3B0gzMlVHafDJmG3OBbVg3wuXLX5CDqJ4hZh1kpku2bj4mQvD1ZD+Bo+XTkrUCx4gCZAGr/vgizCjQDt4hEz83/9sD+FQP7Phwcfzx3AkWyg01Tb22n8KcF5bg/oy6I30t0eOr/llHtf/spc6PYVY5BZyIqsC7wv9RWaJfPvoTt/MYuni7wlL5zdaSBtzCBtKADAgEXooGsBIGpQLxhefwgE1t2sjQg+R0KYIhuUh2YhsdAXNmqkDt8dYVY+vczAA5UGPoghBgoPDdD/RAcF1I8XQMNaMQRwVfI+MGLxL6kVGtUbnizUf7o1jmDfvZ09+9TZqnqUXuMDd+IpvgnWI5K5bI6M4PWeDY9Exk2GmVlxBZ3pCREkcE/ke2A53CaZ6dF8OGEbSWWd4x/ec5EqxqeyfAvbsfxaJ6nnh9BK7msOMQBzw==

Response

WWW-Authenticate: Negotiate oYGIMIGFoAMKAQGhCwYJKoZIgvcSAQIConEEb2BtBgkqhkiG9xIBAgIDAH5eMFygAwIBBaEDAgEepBEYDzIwMTAwNzEyMDk1MzQ4WqUFAgMGSpSmAwIBKakKGwhDUzAyLkNPTaolMCOgAwIBA6EcMBobBGhvc3QbEmNzMDJhcHAwMS5jczAyLmNvbQ==

and a following request with

Authorization: Negotiate oYIEnzCCBJuiggSXBIIEk2CCBI8GCSqGSIb3EgECAgEAboIEfjCCBHqgAwIBBaEDAgEOogcDBQAgAAAAo4IDqWGCA6UwggOhoAMCAQWhChsIQ1MwMi5DT02iJTAjoAMCAQKhHDAaGwRIVFRQGxJjczAyYXBwMDEuQ1MwMi5jb22jggNlMIIDYaADAgEXoQMCAQyiggNTBIIDT0yHCikaYn0FY3dNwR4Eo4ma+tiJpbeAiiDkjMnpGzphbxn5OryeeIzoPxOHd2o84uEOlAl2dpTBGpZ5YxFbO3o4BFFIUcATEX5TiORQVuYO606oywDlIXjow6rz8N6HyITZm/CLmCXOXG0zrtSldD6QcQ5hTP5A7NlPGSl16ULaDTobBi9lRvpvn6kIM4BRWOJyNQmtUqXRV8vjkuodnbDFhxieRwy3QhD+HqVja+Kqwcw1nEhnWHEsUhw+31WFFbH1g0bD212xQBW7SflrTw6YF8laFa80AbU8QqkgDXcTFj6FmHBwb87NbSNkPZrOGKVBVN8VEc+L1fy5i41q+hogihLYXVtLTrO7tvYW4NmWa6T+2K2cft1GI9HZLmPJBKpX7sggb9pvYnH0I6jsbjQvjV8203eToCPI+doN0pc/ba4RhjHvIDcjtHkhpEe3kvpcYhYZfdQax4wat1Zaeqomqlaf4TqMukEYctLt5x/NpC4ETVnzgbUalOU3wUrE03l4AyMpUu6n/GREgDzyfri8IaQNGbeR9AnUUvf/M6SwEc1OABmdDdAdi+9h1xMlHcBClP+EsXfDJghzez/bp1iuQWv3EzgsnMKmLX6MinDyjjVxyPacYtgZGswUfdlXwbRPpQ4s3VWYfyHPYltrGSFZgRBccQE6Dj9Y6I/WSz1dhIcqDMIRx+8AaiAeujpDBa4dtR8fKhzvkx5AGJpGn7feRena2wznjU+4H9rt6jeA2Y+3Wh8dcfBUYk/CqBvciN1DdPXtf/vNCszlo6wf5VGGPxk49Lhj7OfKdGWmEGNXbqM4ReOQgImKvLk4plqn2BLLW6Up+KVCXivibx9+HCSuMc36n0WonsCGh4U21iTS8Yg49xFQ4LeShdjt/Ds8gfv85nBcho6jINXkq2v4xuQDSs0C8T58oVN5p4Zof3M80o2AaoNr3vkLZ1pTqXDjk8jH+YYz15E+UOO4TWvdShT5f6kcLUebGFHQiamO+8nSagwYbTWRL1JH+GbrFQCf2ffv2GJEYqBakQW96CwbxVZqIrMFAMt/QBfvUj7LUFMS/DaHrTajvAlHui2G6y86S+c2ykgOMMXSe6N+3rNej9faF0zp0Axmij+gNfi01lekgbcwgbSgAwIBF6KBrASBqcEFv86hjFvokwjI5uDEI4oYOLSnfoZk2Eb4NWWU30+a5hSqiDpCjaVjs4+SQWA6ZhIM/f6IePTMLD86qCP9/9QTvkD3tlwwFrzEOc3vWxP1fNM9rGrAmVyzUAXaZMrvLTz+in9/1wsBKllcQeuc3TMk2GFjzmFMmVO5trX9fQB2dWkfcRh31RC9bVJb87BqUkYc4iBjjpf9rZvOQjJIMypnxhLxbDg69ek=

Then the ending response with the two types of www-authenticate only.

posted @ 7/18/2010 9:56 PM by James Allderidge

JQuery: Continuous Integration with QUnit, MSTest and WatiN

Background

We’re in the initial stages of a new project here at iMeta that looks likely to have a large proportion of logic in the client browser rather than the web server. JQuery is the ideal tool for the job here and it just so happens that I’m a huge fan of it too!

Before the project gets properly underway I want to experiment with unit testing JQuery. My ultimate aim being to develop a pattern for including JQuery unit tests in CI builds – with this achieved I can add real value to the project going forward.

After a bit of research I came across the following great blog post, it’s a worth a read as a primer for the remainder of my post - http://www.lostechies.com/blogs/joshuaflanagan/archive/2008/09/18/running-jquery-qunit-tests-under-continuous-integration.aspx.

Joshua wrote his post in 2008, as a result WatiN’s codebase has since moved on. I also wanted to use MSTest rather than NUnit, purely because we will be running our builds on a Team Foundation Build server. This meant that I needed to find a replacement for NUnit’s IterativeTest add-in (or the more up to date TestCaseSource attribute) in MSTest. Another bit of research unearthed http://codeclimber.net.nz/archive/2008/01/18/How-to-simulate-RowTest-with-MS-Test.aspx – perfect!

Code

Pulling all this research together gave a nice end result, which I hope will benefit others.  You will probably notice that my JavaScriptTester class is much simpler – this is firstly because of advances in the WatiN codebase for finding page elements and secondly because I only check and report pass/failure for whole QUnit tests rather than for each individual assertion within that test. You could easily extend the below to report on individual QUnit assertions should your scenario require it.

JavaScriptTester.cs
  1. namespace QunitJack.Tests
  2. {
  3.     [TestClass]
  4.     public class JavaScriptTester
  5.     {
  6.         private IE _ie;
  7.  
  8.         [TestInitialize]
  9.         public void TestInitialize()
  10.         {
  11.             _ie = new IE();
  12.             _ie.ShowWindow(NativeMethods.WindowShowStyle.Hide);
  13.         }
  14.  
  15.         public TestContext TestContext { get; set; }
  16.  
  17.         [DeploymentItem("QunitJack.Tests\\JavaScriptTester.xml"), TestMethod]
  18.         [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "|DataDirectory|\\JavaScriptTester.xml", "Row", DataAccessMethod.Sequential)]
  19.         public void RunQUnitTests()
  20.         {
  21.             _ie.GoTo(string.Format("http://localhost:90/{0}", TestContext.DataRow["Filename"]));
  22.             _ie.WaitForComplete(5);
  23.  
  24.             AssertQUnitTestResults();
  25.         }
  26.  
  27.         private void AssertQUnitTestResults()
  28.         {
  29.             var liElements = _ie.ElementsWithTag("li").Filter(x => x.Parent.Id == "qunit-tests");
  30.             foreach(var liElement in liElements)
  31.             {
  32.                 Assert.IsTrue(liElement.ClassName == "pass", liElement.DomContainer.ElementsWithTag("strong")[0].Text);
  33.             }
  34.         }
  35.     }
  36. }

JavaScriptTester.xml
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <Rows>
  3.   <Row>
  4.     <Filename>Test1.htm</Filename>
  5.   </Row>
  6.   <Row>
  7.     <Filename>Test2.htm</Filename>
  8.   </Row>
  9. </Rows>

There are a couple of great QUnit blog posts over at http://indomitablehef.com/?cat=35, I have made use of the static Assert methods and dynamically setting up/tearing down the DOM.

Test1.htm
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <html>
  3. <head>
  4.     <link rel="stylesheet" href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" type="text/css" />
  5.     <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
  6.     <script type="text/javascript" src="http://github.com/jquery/qunit/raw/master/qunit/qunit.js"></script>
  7.     <script type="text/javascript" src="Scripts/Assert.js"></script>
  8.     <script type="text/javascript" src="Scripts/DOMSetup.js"></script>
  9.     <script type="text/javascript" src="Scripts/DOMTearDown.js"></script>
  10.  
  11.     <script type="text/javascript">
  12.         $(document).ready(function() {
  13.        
  14.             test("renderJsonGridTests", function() {
  15.  
  16.                 DOMSetup('<div id="target" />');
  17.  
  18.                 var json = jQuery.parseJSON('{ "tableId" : "foo" }')
  19.                 $("div#target").html('<table id = "' + json.tableId + '"></table>');
  20.  
  21.                 Assert.AreEqual(true, $("#target > table").length == 1, "table exists");
  22.                 Assert.AreEqual("foo", $("#target > table").attr("id"), "table has correct id");
  23.  
  24.                 DOMTearDown("div#target");
  25.                 
  26.             });
  27.  
  28.         });
  29.     </script>
  30.  
  31. </head>
  32. <body>
  33.     <h1 id="qunit-header">
  34.         QUnit example</h1>
  35.     <h2 id="qunit-banner">
  36.     </h2>
  37.     <h2 id="qunit-userAgent">
  38.     </h2>
  39.     <ol id="qunit-tests">
  40.     </ol>
  41. </body>
  42. </html>

 

Summary

I’m sure that the above approach to our JQuery CI will evolve as the project does – but as an initial pattern I think it will do the job. Any refinements that I make will be added to this post somehow.

posted @ 7/15/2010 10:57 PM by Mike Godfrey

The Task Parallel Library Series - Task Parallelism

So far, we've looked the the motivations behind concurrency and Data Parallelism as a technique to introduce concurrency into your code. We've also looked at some simple examples of Parallel.For() and Parallel.ForEach(). In this post we're going to explore the other main way that concurrency can be harnessed, Task Parallelism.

Data parallelism was all about executing the same block of code on many different data items. Task parallelism is about concurrently executing different blocks of code, perhaps operating on the same data, perhaps on different. What's important is that the tasks are, as far as possible, independent. If there are dependencies between them things will rapidly get more complex, and all those issues we discussed in data parallelism such as corruption and deadlocks will raise their heads.

Let's look at an example. Firstly, in the familiar sequential world:


public void OnlineStore()
{
	TakeOrder();
	SendOrderReceivedNotification();
	PrepareInvoice();
	SendInvoice();
	PickGoodsFromShelf();
	UpdateStockControl();
	PackGoods();
	ShipGoods();
	SendDispatchedNotification();
}

In here, we have a whole bunch of different methods (tasks, code blocks, call them what you want). Some are dependent on others, some aren't. Let's see how it could be parallelised (pseudocode only):


public void Amazon()
{
	TakeOrder();
	
	in parallel do
		=> SendOrderReceivedNotification();
		=> DealWithInvoicing();
		=> DealWithTheGoods();
}

public void DealWithInvoicing()
{
	PrepareInvoice();
	SendInvoice();
}

public void DealWithTheGoods()
{
	PickGoodsFromShelf();

	in parallel do
		=> UpdateStockControl();
		=> SendGoods();
}

public void SendGoods()
{ 
	PackGoods();
	ShipGoods();
	SendDispatchedNotification();
}

A bit more code, but still readable (I'd actually argue a bit more readable since the first method was, IMO, doing way too much stuff). Basically all we've done is divide the tasks into those that are dependent and those that aren't. For the independent tasks, we're using a new "in parallel do" construct to indicate to the language / runtime that these can be run on different threads. In the new code, the longest chain from start to completion is 5 steps compared to the 9 steps in the sequential code, so we should expect some speedup when run on a multi-core system.

How much speedup? Since we've dropped from 9 steps to 5, does that indicate that we should now be almost twice as fast? Clearly not, since each step is unlikely to have the same sequential execution time. Let me introduce Gene Amdahl who formulated the fundamental limits to what parallelisation could achieve. In essence, he stated that the maximum speedup that can be achieved through concurrency is limited by the sequential part of the program. That is, if you have a program that takes 10 hours to run and within that there is a task of 2 hours that cannot be parallelised, then the fastest that program can run, regardless of the number of processors that can be thrown at it, is 2 hours. Not exactly rocket science, but it earned the title of Amdahl's Law; go take a look if you want to see the maths (it's not hard). Data Parallelism enjoys the fact that the sequential parts can be very small, and so the possible speedups can be truly enormous. Task parallelism is more restricted, in that it's limited to how fast the longest (in time, not code) dependent chain of tasks can run.

If anyone's reading all this, are you spotting a theme yet? Concurrency is important (and will get more so), but dependencies are the problem. Dependencies introduce the bottleneck beyond which you're relying on the hardware to improve it's sequential execution speed to see improvements. And we've already seen that that's unlikely. Dependencies are also the thing that cause you to start dropping locks and other synchronisation mechanisms in your code, obscuring your "business rules" and introducing the risk of hard-to-test, hard-to-diagnose bugs. Loosely coupled, independent code is something that you should strive for, and immutable data structures assist greatly in this. I'm thinking that perhaps the "I" in SOLID could be re-purposed...

That should give an idea as to what Task Parallelism is all about. In the next post, we'll look at how to do this in .Net 4.0.

posted @ 7/12/2010 4:39 PM by Steve Strong

The Task Parallel Library Series - Parallel.For & Parallel.ForEach

In the previous post we discussed the principles behind data parallelism, in this one we'll show how to implement it in .Net 4.0. This will probably be a short post, since it's really simple. Here's a regular sequential loop:


var data = GetTenThousandElementArray();for (var i = 0; i < 10000; i++)
{
 DoSomeProcessing(data[i]);
}

And here's the parallelised version:


var data = GetTenThousandElementArray();Parallel.For(0, 10000, i =>
{
 DoSomeProcessing(data[i]);
});

Pretty simple stuff, and highly readable. Just switch from the C# for keyword to a call to the static For() method on the System.Threading.Tasks.Parallel type. In it's basic form, this method takes three parameters - the "from" value (inclusive), the "to" value (exclusive) and the loop body itself (shown as a lambda here, but an anonymous delegate or full-blown named delegate will also work just fine)1.

What about data that doesn't have a known range, such as an IEnumerable<T>, where you don't know how many values may be retrieved? In sequential code, you'd handle that with:


var data = SomeSourceOfIEnumerable();   foreach (var val in data)
{
 DoSomeProcessing(val);
}

To switch this to parallel execution, you can probably guess what you need to do:


var data = SomeSourceOfIEnumerable();   Parallel.ForEach(data, (val) =>
{
 DoSomeProcessing(val);
});

Again, the parallel version is pretty much identical to the sequential but the intent is quite clear. What you should notice from both examples is that we aren't dealing with threads. We aren't having to look at how many cores we have available, or coding up some algorithm for partitioning the data. We simply state the intent, and let the runtime take it's best shot at how to execute the code. And it's the runtime that has all the knowledge as to what state the environment is in right now, so arguably it's in the best position for making those decisions.

In the rare scenarios where it doesn't do it "right", or where you know something about your data source that could lead to a more optimal way of processing, there are various hooks available so that you can take on more responsibility; depending on how long this series gets and on whether anyone asks, we may look at some of them in later posts.

You may also be wondering how to handle exceptions, how to break out of the loop and how to cancel the loop. Those are all important things that are frequently required, and they also tend to mess the code up if you're doing it by hand. In future posts we'll examine each of these and show how it is achieved through the TPL.

As we discussed in the previous post, the examples above assume that the DoSomeProcessing method is itself thread-safe, which is ideally achieved by not accessing any shared state. That doesn't mean that you can't share stuff, just that each loop iteration needs to be careful not to tread on anyone else's toes. For example, this is fine:


var data = GetTenThousandElementArray();Parallel.For(0, 10000, index =>
{
 data[index] = data[index]*data[index];
});

Although each loop iteration is accessing the data array in parallel, each access is only dealing with a single distinct element. Since there is no concurrent access to a single memory location, this code is completely safe. Compare that with:


var sum = 0;
Parallel.For(0, 10000, index =>
{
 sum += data[index];
});

In this code, each iteration is accessing the single sum field and invalid results are likely2. Note that aggregate operations like this are a pretty common requirement, and there is a way to achieve this within the TPL which we'll look at soon. For now, I think that's enough. Next post will be on Task Parallelism, see you there.


1The observant amongst you (and ReSharper) will say that you can replace that lambda as follows:


Parallel.For(0, 10000, DoSomeProcessing);

Feel free to do that in your code, but for this series I'll stick with the longer version just to highlight the similarities with the sequential code.

2Only likely? Well, yes. Here is an example of the fun you can have testing concurrent code - if you write this code and run it, chances are it will work just fine. If you've got a single core machine (or a single core assigned to your VM), then the odds are in fact pretty good that it will run correctly. Why? Well, for it to produce invalid results, a thread context switch has to happen at just the right place. And you've got no control over that, it's all down to the Windows scheduler. What you can be sure of is that it will go wrong shortly after shipping; there's a guy called Murphy who can explain that to you! Later on in this series, I'll talk some more about testing and about the CHESS tool from Microsoft Research that can help out. One step at a time though.

posted @ 7/1/2010 3:57 PM by Steve Strong

ViewBox, WrapPanel and a Resizable UI for Windows Phone 7

 

After reading Matthias’s post about porting WrapPanel and DockPanel from the Silverlight toolkit to WP7 I was interested in creating a multi-scale ui for the phone and set about it, however the other piece of the puzzle that’s needed to acheive this is the ViewBox which was part of the Silverlight toolkit. 

The source for the ViewBox control can be downloaded from the November 2009 version of the Silverlight Toolkit, however as with the WrapPanel and Dockpanel there are only a few files you actually need:

  • Viewbox.cs
  • StretchDirecton.cs
  • NumericExtensions.cs
  • Resources.resx

To save you the leg work, I’ve parcelled them up into a zip of the source project or the dll for you to download to save some time.

Once you have downloaded or built the DLL you can add a reference to it and then access it in Expression:

image

Now that we have a ViewBox we can scale the control hosted inside it:

image

This will scale the button up to 400 pixels wide like:

image

By adding a slider to the UI we scan databind the size of the ViewBox to the value of the slider to make the button resize:

image

image  image

And by adding the WrapPanel in we can fill it full of resizable buttons:

image

image image

And for the extra Silverlight sauce, add a fluid movement behaviour onto the wrap panel:

image

posted @ 6/29/2010 4:48 PM by Neil Rees

Adding and Choosing Contacts using the WP7 Emulator

 

The Windows Phone Emulator contains support for applications to interact with the inbuilt Phone resources by way of the Choosers and Tasks contained within the Microsoft.Phone.Tasks.dll assembly.  However the functionality of some of them is limited by the fact that the emulators operating system is locked down so there’s no data on the phone for the Choosers to operate against.

For example, using the PhoneNumberChooserTask to select the phone number of a contact brings up a page showing that there are no contacts:


PhoneNumberChooserTask pct = new PhoneNumberChooserTask();
pct.Show();


image

Through the emulator UI there’s no way to add contacts into the phone’s operating system, but by using the SavePhoneNumberTask we can save a contact into the phone for later use.

This code


SavePhoneNumberTask savePhoneNumberTask = new SavePhoneNumberTask();

savePhoneNumberTask.PhoneNumber = "08452414145";
savePhoneNumberTask.Show();

Tries to add that phone number and associate it with a contact – or add a new contact. By selecting “add a contact”:

image

We can review the phone number the application is trying to save:

image

And then create a new contact record (by hand) for the number to be associated with:

image

When that record is saved, we are taken to the profile page for the contact. 

image

By clicking the pin icon in the application bar we can pin this contact to a tile which provides us with a route to come back and edit the details of the contact should we need to:

image

Now when we run up the app and use the PhoneNumberChooserTask the contacts list now contains an entry which we can select:

image

And our delegate now gets called back and we can inspect the number of the contact:

public override void OnChooserReturn(object sender, EventArgs e)
       {
           if (e is Microsoft.Phone.Tasks.TaskEventArgs<PhoneNumberResult>)
           {
               TaskEventArgs<PhoneNumberResult> result =
                   (TaskEventArgs<PhoneNumberResult>)e;

               MessageBox.Show(result.Result.PhoneNumber, "Phone Number", MessageBoxButton.OK);
           }
       }

 

We can now emulate choosing a contact from within a Silverlight app:

image

posted @ 6/28/2010 10:30 AM by Neil Rees