October 2005 - Posts
It came as a bit of a surprise to me that Parallel activities in Windows Workflow Foundation are not in fact asynchronous. Since investigating I've seen that several people have mentioned this fact but I thought a more descriptive example might be in order.
Consider the following sequential workflow hosted in a console application. In it I have one parallel activity with three branches. Each branch has two code activities. There is a final code activity at the end of the workflow.
In each code activity I merely echo a number matching the Code activity number. So activity Code1 displays "1" and Code2 displays "2". Note that I have numbered them across the branches. Code 7 displays the word "Done". Now, if parallel activities executed their branches asynchronously you'd expect that I would see the results in a seemingly random set of "1/4", "2/5", and "3/6". Instead what you get is this:
The Scheduler inside the WF (Formerly known as WWF) executes the first activity of each branch before moving to the second as well as moving through the branches in order. Execution takes place on the same thread from the CLR Threadpool for each activity.
Tomorrow Soon, I'll show one example of how to make each of the branches execute asynchronously.
Here's a link to the sample workflow project.
I've received quite a few requests for a C# version of the sample code that came with my article. So, here is a C# version of the 1.1 custom collection. If I get inundated with requests I'll port the 2.0 version, but otherwise it's probably not necessary. There are a couple of changes that you should be aware of.
1. StudentComparer
In the article I mentioned that I was turning "Option Strict" off on the file containing the StudentComparer so that I could leverage Visual Basic's ability to do type conversions at runtime. In C# this isn't an option and so the source for the CompareProperties method has changed. I've added a switch to compare the properties differently based on the type of the property being sorted on. You'll notice that I've only added string and int. If you have a custom class with other types that you want to be able to compare, you will need to add to the choices accordingly.
2. Events
One of the nice things about Visual Basic is that it does a lot of the mundane work for you. In porting the code tonight I came across one example of a Visual Basic compiler optimization that can only be described as "GOODNESS". Let's start by looking at two seemingly identical methods in VB and C#.


This is a simple property that when the value is changed fires a Changed event. While they look the same, what the C# and VB Compilers do with the Set methods for this property are very different. So much so that the C# property (as coded) will cause the any changes to fail. To see what's happening, let's take a look at the Disassembly as C# source code via the magic of Lutz Roeder's Reflector.
Here's the C# version.
And Here's the VB version.
You can see that the VB.NET Compiler was kind enough to wrap the event method in an if to test that there was actually something to call. The C# compiler expects you to do this yourself. Now many of you C# coders out there might have spotted the missing if right away. But the real question is if you should ALWAYS wrap a delegate call in an if statement, why doesn't the C# compiler just do it for you?
This code has been updated. Here is the newer version. Note that this code is still quite old and doesn't use Generics so use it if you like but there are better ways to accomplish these types of collections now.
Download the C# Sample Code
Wow, It's been way too long since I blogged. I've been pretty busy lately with PDC and the MVP Summit, both of which were great events. So as an excuse to post something hopefully useful, I'll take this opportunity to answer a question from a reader about my earlier post on using data from SharePoint lists.
Q: Joe Chan writes "How do you create a web reference to a subsite containing a space in the URL?"
A: Let's start by looking at what is going on behind the covers when you add a web reference. When you use the familiar dialog box to add a web reference to a .NET based web service, Visual Studio shows you the web service helper page and at the same time requests the WSDL for the web service by calling the web service url with a "?wsdl" query string. The URL is similar to this: http://myserver/_vti_bin/Lists.asmx?wsdl. The ASP.NET web service infrastructure knows that this query string means to return the WSDL for the service which is then generated (using Reflection) and returned to the browser as XML. The Add Web Reference dialog then uses that WSDL to generate a proxy class for the web service.
For reasons I'm not entirely certain of, SharePoint can't return the WSDL for a web service with a space in the URL. It works fine for a regular ASP.NET web service, but if you browse to http://myserver/Sub%20Site/Lists.asmx?wsdl you'll see a "File Not Found" error. Now while I'm sure that some other true SharePoint diety could probably tell me why this is, it's such a minor inconvenience that it's not worth investigating.
Here's the workaround. Create a web reference to your primary SharePoint site (I'm assuming here that there isn't a space in it's URL). Then click on the "Show All Files" button in the Solution Explorer. Expand the web reference all the way and your screen should look something like the one below.
Notice the Reference.vb file. This file contains the .NET proxy code generated using the WSDL from your site's web service Because SharePoint uses the same services no matter which site you are requesting, you can simply change the hardcoded (who's idea was that anyway) URL in the constructor to be the URL for your subsite and it will work like a charm. Here's some sample code for that.
More Posts