Sep 16 2010

Custom Windows Workflow activity for dependency resolution–Part 1

Category: .NetRory Primrose @ 12:41

The previous post talked about the issues with supporting Dependency Injection in WF4. The nature of Windows Workflow means that there is no true support for Dependency Injection. Using a custom extension and activity will allow for pulling in dependencies to a workflow while catering for the concerns outlined in the previous post. This series will refer to the dependency injection concept as dependency resolution because this technique is more aligned with the Service Locator pattern than Dependency Injection.

This first part will go through the design goals of the custom activity.

The custom activity will have the following characteristics:

  • Operate as a scope type activity (like ForEach<T> or ParallelFor<T>)
  • It can hold a single child activity
  • Resolved instance is available to all child activities
  • Resolved instance is strongly typed
  • Support named resolutions
  • Support persistence
  • Dependency should only be resolved when they are referenced
  • Dependency should be torn down when the activity completes
  • Dependency should be torn down when the activity is persisted
  • Dependency must be resolved against when referenced after the activity is resumed from a bookmark
  • Provide adequate designer support for authoring the child activity

The biggest sticking point identified for dependency resolution in a workflow activity is how to deal with persistence. Using a Dependency Injection container as the mechanism for creating the dependency instance means that there can be no guarantee that the instance is serializable. An exception will be thrown by the workflow engine if a workflow contains a reference to an instance that is not serializable when the workflow is persisted.

There are several scenarios that this implementation needs to cater for regarding persistence.

  1. A workflow execution where an instance is resolved and used without any persistence
    image

    This scenario is reasonably simple. The instance will be resolved when it is referenced. It will be torn down by the Dependency Injection container (via the extension) when the activity completes.
  2. A workflow execution where instances are resolved and used before and after a bookmark
    image

    This scenario requires that the first resolved instance is torn down when the bookmark causes the workflow to persist. The second instance resolution needs to have enough information to create an instance after the workflow has been resumed from the bookmark. The activity then needs to ensure that the second instance is torn down when the activity completes.
  3. A workflow execution where an instance resolution scope surrounds a bookmark
    image

    As far as the implementation goes, this scenario is actually the same as the second. When the bookmark is resumed, there needs to be some information stored about the instance resolution so that the instance can be recreated again when it is referenced. This instance is then torn down when the activity completes.

The problems of persistence

The central issue with persistence of a dependency in WF is that the dependency instance may not be serializable. The support for persistence in this custom activity is a design issue more than an implementation issue. You may notice that the InvokeMethod activities in the above screenshots make a reference to an Instance property. This indicates how persistence is supported under the covers.

The answer to this problem is to persist the details of the resolution rather than the resolved instance itself. This means that we need to serialize the resolution type and the resolution name for each defined resolution in the workflow. Using a handler class will allow serialization of the resolution definition. It is this class that is provided to the child activity. This handler type specifically identifies that the actual resolved instance is not serializable. Using this handler type also provides the ability to resolve the instance only when it is requested.

The next post will go through the implementation of the handler and the extension classes.

Tags: ,

Sep 15 2010

Dependency injection options for Windows Workflow 4

Category: .NetRory Primrose @ 11:42

I’m a fan of Dependency Injection for all the benefits that it brings. Unfortunately dependency injection is not really supported with Windows Workflow.

Dependency Injection is a pattern in which dependencies are calculated outside an entity and provided to the entity for it to use. The Dependency Injection container is responsible for creating and managing these dependencies and injecting them onto the entity.

WF does not fully support this model. Any dependencies calculated outside a workflow must be provided to the workflow execution engine as a dictionary of input parameters. A Dependency Injection container can be used resolve the dependencies, however providing them to the workflow via the workflow engine is a manual process. This means that constructor, property and method injection are not supported as you cannot use a container to resolve or build up a workflow instance.

There are two ways that you can get dependencies to be available on a workflow. These are via arguments or via a custom extension/activity implementation.

There are a few considerations that dependency support in workflow should cater for. These are the amount of plumbing code required, validation of dependencies and support for persistence.

Dependencies via workflow arguments (the almost Dependency Injection pattern)

Using workflow arguments to provide dependencies is similar to property injection. Using handler classes is helpful for abstracting the workflows from callers of the assembly. Dependency Injection is used to create the handler with required dependencies. The handler then provides these dependencies to the workflow by manually pushing them through to the workflow execution as input parameters when a handler method is invoked. This produces decent amounts of manual code that pollutes the handler classes.

Workflows need to manually validate the arguments it has been provided. The workflow can’t make any assumptions about what has been provided to it so manual guard checks need to be added to the workflow. This is then further implementation in the workflow that requires testing.

Workflow arguments may not be serializable. The workflow isn’t responsible for creating the arguments and can’t guarantee that the arguments are serializable. Persisting a workflow to durable storage (SQL Server for example) would only be supported if all the dependencies were serializable. An exception would be thrown if a non-serializable argument was provided and the workflow was persisted and unloaded.

Pros

Cons

  • Workflow invocation code is messy
  • Explicit dependency validation required
  • Persistence support not guaranteed

Dependencies via custom extension/activity (the Service Locator pattern)

Using a custom extension or activity is more aligned with the service locator (anti-) pattern than dependency injection. A Dependency Injection container should still be used in this method to resolve the dependencies. This is because the Dependency Injection containers have the logic to create complex dependencies and typically have some aspects of instance lifetime management.

The first benefit of this method is that there is no plumbing code to provide these dependencies to the workflow engine. The dependencies will be requested by an activity inside the workflow execution and be resolved at that point (hence a service locator pattern).

Dependencies resolved inside the workflow execution will not require validation of the dependencies. A Dependency Injection container would normally throw an exception if a dependency can’t be resolved. If this is not the case then the custom logic involved can provide that validation.

Serialization of dependencies is still an issue with this method. The custom implementation can cater for this however and will be covered in the next post.

Any custom implementation in WF that uses this method should leverage a custom extension even if a custom activity is also used to provide the dependency to the parent workflow. This will allow the same dependency resolution logic to be available from any activity or extension running in the workflow execution. Using an extension is also a good way to abstract the Dependency Injection container from any custom activities that request a dependency.

Pros

  • Workflow invocation is clean
  • Implicit dependency validation

Cons

  • Slightly more coupled to Dependency Injection container
  • Persistence support not guaranteed, although can be fully supported

Conclusion

Most of my workflow experience has used workflow arguments to provide dependencies. I tend to be a purist so I prefer a true Dependency Injection implementation over a Service Locator implementation. I am however finding the advantages of using a custom extension/activity to resolve dependencies in WF4 far outweigh the disadvantages.

Persistence is the main disadvantage with the custom extension/activity method outlined above. The next post will provide an implementation that fully caters for persistence.

Tags: ,

Sep 10 2010

TFS Build fails for no indicated reason with code contracts in test assemblies

Category: .NetRory Primrose @ 12:02

This has been a curly one for a few months and I’ve finally had some time to resolve the issue. My team has been running TFS Build 2010 with gated check-ins where the build does MSI deploys then runs unit and integration tests.

All of a sudden the builds started failing with no indication as to why. The build activity log just stops and does not contain errors. The Microsoft build log file also does not contain any errors. The event log on the build server does shed some light on the situation however.

(MSTest.exe, PID 1868, Thread 1) Exception thrown when enumerating assembly: System.IO.FileLoadException: Could not load file or assembly 'MyProject.Services.Business.UnitTests.Contracts, Version=1.0.449.0, Culture=neutral, PublicKeyToken=0e60eebea588ffe8' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)
File name: 'MyProject.Services.Business.UnitTests.Contracts, Version=1.0.449.0, Culture=neutral, PublicKeyToken=0e60eebea588ffe8' ---> System.Security.SecurityException: Strong name validation failed. (Exception from HRESULT: 0x8013141A)

The Zone of the assembly that failed was:
MyComputer
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at Microsoft.VisualStudio.TestTools.TestTypes.Unit.AssemblyEnumerator.EnumerateAssembly(IWarningHandler warningHandler, String location, ProjectData projectData, ObjectHandle assemblyResolverWrapper)
   at Microsoft.VisualStudio.TestTools.TestTypes.Unit.AssemblyEnumerator.EnumerateAssembly(IWarningHandler warningHandler, String location, ProjectData projectData, ObjectHandle assemblyResolverWrapper)
   at Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAttributeEnumerator.Read(ITestTypeExtensionClientSidesProvider provider, IWarningHandler warningHandler, String assemblyFileName, ProjectData projectData, TestRunConfiguration testRunConfiguration)

This didn't make any sense. The initial workaround was to determine whether contracts where actually being used in the assembly for which the contract assembly is generated. Contracts where not being used in the first assembly that failed in this way so I disabled the contract assembly and submitted a new build. The next build fell over with the same problem on a different assembly.

I looked into the testsettings file configured for the build to see if code coverage was enabled as this also changes the assembly and re-signs them. This wasn’t the case, code coverage was disabled. I also tested the build with no testsettings configured on the build definition.

A quick search came up with this forum entry about code contracts and strong name verification failures. The Microsoft response is that code contract assemblies are not loaded. This quickly lead me to realise where the problem is. Something is loading the code contract assembly when it shouldn’t be. The most likely source of the problem is the build configuration where it identifies test assemblies to run.

The default configuration for new build definitions is to resolve test assemblies with the file spec of **\*test*.dll. This file spec does a recursive directory search for any dll that contains the word test.

The naming of my test projects is like the following:

  • *.UnitTests.dll
  • *.IntegrationTests.dll
  • *.LoadTests.dll

This allows for build definitions to run specific types of tests by searching against these types of file masks. The default build definition will pick up all of these.

The strong name verification issues comes into play when there is a test assembly that compiles a code contract assembly. The default build definition file mask will pick up these contract assemblies as well because

  1. the file spec is recursive and so the CodeContracts directory is searched, and
  2. the contract assembly will be named *.UnitTests.Contracts.dll

So the build definition file spec is finding a match on the contract assemblies and then asks mstest.exe to run any tests found in them. This is where the contract assembly is getting loaded and then strong name verification fails.

The simple fix is to update the test assembly file spec to **\*Tests.dll to ensure that filenames like *\CodeContracts\*.UnitTests.Contracts.dll do not get picked up and loaded.

Tags:

Aug 18 2010

Getting meaningful exceptions from WF

Category: .NetRory Primrose @ 08:33

Overall I love the changes made to WF4. The latest workflow support is a huge leap forward from the 3.x versions. Unfortunately both versions suffer the same issues regarding feedback for the developer when exceptions are thrown.

Consider the following simple workflow example.

image

namespace WorkflowConsoleApplication1
{
    using System;
    using System.Activities;

    class Program
    {
        static void Main(string[] args)
        { 
            try
            {
                WorkflowInvoker.Invoke(new Workflow1());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

            Console.ReadKey();
        }
    }
}

This example provides the following output.

System.InvalidOperationException: Something went wrong
   at System.Activities.WorkflowApplication.Invoke(Activity activity, IDictionar
y`2 inputs, WorkflowInstanceExtensionManager extensions, TimeSpan timeout)
   at System.Activities.WorkflowInvoker.Invoke(Activity workflow, TimeSpan timeo
ut, WorkflowInstanceExtensionManager extensions)
   at System.Activities.WorkflowInvoker.Invoke(Activity workflow)
   at WorkflowConsoleApplication1.Program.Main(String[] args) in e:\users\profil
edr\documents\visual studio 2010\Projects\WorkflowConsoleApplication2\WorkflowCo
nsoleApplication2\Program.cs:line 12

Exceptions thrown from the workflow engine identify the exception type and message but do not contain an accurate stack trace. Exceptions are caught by the workflow engine and re-thrown when WorkflowInvoker.Invoke is used. This means that the stack trace identifies where the exception has been re-thrown rather than where the exception was originally raised.

Debugging WF activities with this constraint is very difficult. Trying to debug your workflows gets exponentially harder with increasing complexity of the workflow system and it's underlying components. This is compounded when the exception (such as a NullReferenceException) doesn't provide enough information by itself to pinpoint where the exception was thrown.

The solution to this is in two parts. The first improvement is to provide more detail in the stack trace and the second is to identify the activity hierarchy involved.

Enhancing the stack trace

Using the throw statement on an existing exception instance wipes out any existing stack trace information. This is why you should never catch ex then throw ex, you should always just use the throw statement by itself. This isn’t possible in the case of the workflow engine as it has caught the exception on a different thread and has no choice but to throw the exception instance back on the original calling thread.

The trick here is to get the exception to preserve the original stack trace when it is re-thrown. Exception has a method called InternalPreserveStackTrace that will do this for us. Reflection must be used here because the method is marked as internal.

The first thing to change is that we need to use WorkflowApplication directly rather than WorkflowInvoker. WorkflowInvoker is great for simplicity but does not provide direct access to the thrown exception before it is re-thrown. Using WorkflowApplication provides the ability to hook the OnUnhandledException action where the exception is available. The reflected InternalPreserveStackTrace method can then be invoked on the exception instance before it is re-thrown.

namespace WorkflowConsoleApplication1
{
    using System;
    using System.Activities;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Text;
    using System.Threading;

    internal class ActivityInvoker
    {
        private static readonly MethodInfo _preserveStackTraceMethod = GetExceptionPreserveMethod();

        public static IDictionary<String, Object> Invoke(Activity activity, IDictionary<String, Object> inputParameters = null)
        {
            if (inputParameters == null)
            {
                inputParameters = new Dictionary<String, Object>();
            }

            WorkflowApplication application = new WorkflowApplication(activity, inputParameters);
            Exception thrownException = null;
            IDictionary<String, Object> outputParameters = new Dictionary<String, Object>();
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            application.OnUnhandledException = (WorkflowApplicationUnhandledExceptionEventArgs arg) =>
            {
                // Preserve the stack trace in this exception
                // This is a hack into the Exception.InternalPreserveStackTrace method that allows us to re-throw and preserve the call stack
                _preserveStackTraceMethod.Invoke(arg.UnhandledException, null);

                thrownException = arg.UnhandledException;

                return UnhandledExceptionAction.Terminate;
            };
            application.Completed = (WorkflowApplicationCompletedEventArgs obj) =>
            {
                waitHandle.Set();

                outputParameters = obj.Outputs;
            };
            application.Aborted = (WorkflowApplicationAbortedEventArgs obj) => waitHandle.Set();
            application.Idle = (WorkflowApplicationIdleEventArgs obj) => waitHandle.Set();
            application.PersistableIdle = (WorkflowApplicationIdleEventArgs arg) =>
            {
                waitHandle.Set();

                return PersistableIdleAction.Persist;
            };
            application.Unloaded = (WorkflowApplicationEventArgs obj) => waitHandle.Set();

            application.Run();

            waitHandle.WaitOne();

            if (thrownException != null)
            {
                throw thrownException;
            }

            return outputParameters;
        }

        private static MethodInfo GetExceptionPreserveMethod()
        {
            return typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic);
        }
    }
}

Changing the example program code to use this ActivityInvoker class rather than WorkflowInvoker now provides some more detailed stack trace information.

System.InvalidOperationException: Something went wrong
   at System.Activities.Statements.Throw.Execute(CodeActivityContext context)
   at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance,
ActivityExecutor executor, BookmarkManager bookmarkManager)
   at System.Activities.ActivityInstance.Execute(ActivityExecutor executor, Book
markManager bookmarkManager)
   at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.Execute
Body(ActivityExecutor executor, BookmarkManager bookmarkManager, Location result
Location)
   at WorkflowConsoleApplication1.ActivityInvoker.Invoke(Activity activity, IDic
tionary`2 inputParameters) in e:\users\profiledr\documents\visual studio 2010\Pr
ojects\WorkflowConsoleApplication2\WorkflowConsoleApplication2\ActivityInvoker.c
s:line 82
   at WorkflowConsoleApplication1.Program.Main(String[] args) in e:\users\profil
edr\documents\visual studio 2010\Projects\WorkflowConsoleApplication2\WorkflowCo
nsoleApplication2\Program.cs:line 11

The stack trace with preservation now includes the stack frames between ActivityInvoker.Invoke and the class that originally threw the exception. This is particularly helpful when the exception was thrown in an underlying component. Unfortunately the architecture of WF does not often provide much of a stack trace in itself. Preserving the stack trace in this simple scenario has added helpful information but not enough to make it really easy to debug.

Identifying the activity hierarchy

Identifying the hierarchy of activities being executed will add further debugging assistance. The Activity class in the 3.x version of WF contained a public Parent property. You could recursively traverse up the chain of parent activities to create a hierarchy of activities to provide this information. This property is still there in version 4.0 but is now internal. Using reflection is again the only option for obtaining this information.

A tweak to the exception logic in the ActivityInvoker class will hook into the Activity.Parent property to calculate the activity hierarchy.

namespace WorkflowConsoleApplication1
{
    using System;
    using System.Activities;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Text;
    using System.Threading;

    internal class ActivityInvoker
    {
        private static readonly PropertyInfo _parentProperty = GetActivityParentProperty();

        private static readonly MethodInfo _preserveStackTraceMethod = GetExceptionPreserveMethod();

        public static Exception CreateActivityFailureException(Exception exception, Activity source)
        {
            // Create the hierarchy of activity names
            Activity activity = source;
            StringBuilder builder = new StringBuilder(exception.Message);
            builder.AppendLine();
            builder.AppendLine();

            builder.AppendLine("Workflow exception throw from the following activity stack:");

            while (activity != null)
            {
                builder.AppendLine(activity + " - " + activity.GetType().FullName);

                activity = _parentProperty.GetValue(activity, null) as Activity;
            }

            return new ActivityFailureException(builder.ToString(), exception);
        }

        public static IDictionary<String, Object> Invoke(Activity activity, IDictionary<String, Object> inputParameters = null)
        {
            if (inputParameters == null)
            {
                inputParameters = new Dictionary<String, Object>();
            }

            WorkflowApplication application = new WorkflowApplication(activity, inputParameters);
            Exception thrownException = null;
            IDictionary<String, Object> outputParameters = new Dictionary<String, Object>();
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            application.OnUnhandledException = (WorkflowApplicationUnhandledExceptionEventArgs arg) =>
            {
                // Preserve the stack trace in this exception
                // This is a hack into the Exception.InternalPreserveStackTrace method that allows us to re-throw and preserve the call stack
                _preserveStackTraceMethod.Invoke(arg.UnhandledException, null);

                thrownException = CreateActivityFailureException(arg.UnhandledException, arg.ExceptionSource);

                return UnhandledExceptionAction.Terminate;
            };
            application.Completed = (WorkflowApplicationCompletedEventArgs obj) =>
            {
                waitHandle.Set();

                outputParameters = obj.Outputs;
            };
            application.Aborted = (WorkflowApplicationAbortedEventArgs obj) => waitHandle.Set();
            application.Idle = (WorkflowApplicationIdleEventArgs obj) => waitHandle.Set();
            application.PersistableIdle = (WorkflowApplicationIdleEventArgs arg) =>
            {
                waitHandle.Set();

                return PersistableIdleAction.Persist;
            };
            application.Unloaded = (WorkflowApplicationEventArgs obj) => waitHandle.Set();

            application.Run();

            waitHandle.WaitOne();

            if (thrownException != null)
            {
                throw thrownException;
            }

            return outputParameters;
        }

        private static PropertyInfo GetActivityParentProperty()
        {
            return typeof(Activity).GetProperty("Parent", BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic);
        }

        private static MethodInfo GetExceptionPreserveMethod()
        {
            return typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic);
        }
    }
}

The change here calculates the activity hierarchy and appends it to the exception message. A custom ActivityFailureException is used to help identify that this an exception handled from the workflow engine. The original exception is still available via the InnerException property.

The output of the program now provides the extended stack trace and the activity hierarchy.

WorkflowConsoleApplication1.ActivityFailureException: Something went wrong

Workflow exception thrown from the following activity stack:
1.5: Throw - System.Activities.Statements.Throw
1.4: Fourth Sequence - System.Activities.Statements.Sequence
1.3: Third Sequence - System.Activities.Statements.Sequence
1.2: Second Sequence - System.Activities.Statements.Sequence
1.1: First Sequence - System.Activities.Statements.Sequence
1: Workflow1 - WorkflowConsoleApplication1.Workflow1
 ---> System.InvalidOperationException: Something went wrong
   at System.Activities.Statements.Throw.Execute(CodeActivityContext context)
   at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance,
ActivityExecutor executor, BookmarkManager bookmarkManager)
   at System.Activities.ActivityInstance.Execute(ActivityExecutor executor, Book
markManager bookmarkManager)
   at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.Execute
Body(ActivityExecutor executor, BookmarkManager bookmarkManager, Location result
Location)

   --- End of inner exception stack trace ---
   at WorkflowConsoleApplication1.ActivityInvoker.Invoke(Activity activity, IDic
tionary`2 inputParameters) in e:\users\profiledr\documents\visual studio 2010\Pr
ojects\WorkflowConsoleApplication2\WorkflowConsoleApplication2\ActivityInvoker.c
s:line 80
   at WorkflowConsoleApplication1.Program.Main(String[] args) in e:\users\profil
edr\documents\visual studio 2010\Projects\WorkflowConsoleApplication2\WorkflowCo
nsoleApplication2\Program.cs:line 11

The combination of these two pieces of information will now allow you to quickly identify where the exception is being thrown in or through your workflow assembly.

Tags:

Aug 6 2010

Developing multi-threaded workflows

Category: .NetRory Primrose @ 07:21

Most people (myself included) assume that the Parallel and ParallelForEach<T> activities in WF4 run each child in parallel on multiple threads. Unfortunately this is not the case. Each child activity is scheduled in the workflow runtime at the same time. The child activities will only start running in “parallel” if one of the branches is in a waiting state. You can read this post which links to this post for some more detailed information

You can achieve multi-threaded parallel execution by using AsyncCodeActivity derived activities (such as InvokeMethod) with the RunAsynchronously set to True running in a Parallel or ParallelForEach<T> activity. Consider the following workflow.

image

Each parallel branch writes the start time to the console, runs a Thread.Sleep for 2, 4 or 6 seconds and writes the end time. The following is written to the console if each InvokeMethod activity has RunAsynchronously set to False.

Starting - 6/08/2010 10:41:38 AM
Starting First - 6/08/2010 10:41:38 AM
Finishing First - 6/08/2010 10:41:40 AM
Starting Second - 6/08/2010 10:41:41 AM
Finishing Second - 6/08/2010 10:41:45 AM
Starting Third - 6/08/2010 10:41:45 AM
Finishing Third - 6/08/2010 10:41:51 AM
Completed - 6/08/2010 10:41:51 AM

Each branch in the parallel is waiting until the previous branch has completed. The following is written to the console if each InvokeMethod activity has RunAsynchronously set to True.

Starting - 6/08/2010 10:47:35 AM
Starting First - 6/08/2010 10:47:35 AM
Starting Second - 6/08/2010 10:47:35 AM
Starting Third - 6/08/2010 10:47:35 AM
Finishing First - 6/08/2010 10:47:37 AM
Finishing Second - 6/08/2010 10:47:39 AM
Finishing Third - 6/08/2010 10:47:41 AM
Completed - 6/08/2010 10:47:41 AM

Each parallel branch has now executed on different threads. The overall affect is that the workflow now runs must faster.

ParallelForEach<T> works in the same manner. This workflow can be refactored to the following:

image

The result without asynchronous processing is:

Starting - 6/08/2010 11:55:09 AM
Starting 1 - 6/08/2010 11:55:09 AM
Finishing 1 - 6/08/2010 11:55:11 AM
Starting 2 - 6/08/2010 11:55:11 AM
Finishing 2 - 6/08/2010 11:55:16 AM
Starting 3 - 6/08/2010 11:55:16 AM
Finishing 3 - 6/08/2010 11:55:22 AM
Completed - 6/08/2010 11:55:22 AM

The result with asynchronous processing is:

Starting - 6/08/2010 11:56:02 AM
Starting 1 - 6/08/2010 11:56:02 AM
Starting 2 - 6/08/2010 11:56:02 AM
Starting 3 - 6/08/2010 11:56:02 AM
Finishing 1 - 6/08/2010 11:56:04 AM
Finishing 2 - 6/08/2010 11:56:07 AM
Finishing 3 - 6/08/2010 11:56:08 AM
Completed - 6/08/2010 11:56:08 AM

What happens when an exception is thrown? If the exception is thrown in the parallel branch, it will stop executing all the other running branches and the exception will be thrown up the call stack. Any exceptions thrown from within the asynchronous code will have the exception pushed back onto the original workflow execution thread and then thrown. Effectively there is no difference regarding where the exception is thrown from, the parallel branches will be stopped.

Tags:

Aug 2 2010

Cleaning a VS2010 solution with a sledgehammer

Category: .Net | My SoftwareRory Primrose @ 07:11

My workplace has been having issues with VS2010 picking up old assemblies since we have been using VS2010 on a complex services solution. The issue usually pops up when executing test runs with the built in support for MSTest. This occasionally happened in VS2008 but is much more prevalent in 2010. The scenario seems to be that somewhere between the IDE and MSTest is picking up assemblies from prior TestResults directories if the assembly can’t be found in bin\Debug or bin\Release directories. This means that the normal clean operation under the build menu is not sufficient to get rid of this problem.

Enter the sledgehammer. I wrote a little utility that will recursively go through each bin, obj and TestResults folder under the solution path and delete everything it can (including read-only files). Any exceptions encountered will be output to the console. The code itself is really simple.

namespace Neovolve.SolutionCleaner
{
    using System;
    using System.IO;
 
    internal class Program
    {
        private static void DeleteDirectory(String directoryPath)
        {
            String[] directories = Directory.GetDirectories(directoryPath);

            for (int index = 0; index < directories.Length; index++)
            {
                String childDirectory = directories[index];

                DeleteDirectory(childDirectory);
            }

            Console.WriteLine("Cleaning directory " + directoryPath);

            String[] files = Directory.GetFiles(directoryPath);

            for (Int32 index = 0; index < files.Length; index++)
            {
                String file = files[index];

                Console.WriteLine("Deleting file " + file);

                try
                {
                    FileInfo fileInfo = new FileInfo(file);

                    if (fileInfo.IsReadOnly)
                    {
                        fileInfo.IsReadOnly = false;
                    }

                    fileInfo.Delete();
                }
                catch (IOException ex)
                {
                    Console.WriteLine(ex);
                }
                catch (UnauthorizedAccessException ex)
                {
                    Console.WriteLine(ex);
                }
            }

            Console.WriteLine("Deleting directory " + directoryPath);

            try
            {
                Directory.Delete(directoryPath, true);
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex);
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine(ex);
            }
        }

        private static void Main(String[] args)
        {
            foreach (String argument in args)
            {
                if (Directory.Exists(argument))
                {
                    ProcessDirectory(argument);
                }
            }

            Console.WriteLine("Completed");
        }

        private static void ProcessChildDirectory(String directoryPath, String childDirectory)
        {
            String[] directories = Directory.GetDirectories(directoryPath, childDirectory, SearchOption.AllDirectories);

            foreach (String directory in directories)
            {
                DeleteDirectory(directory);
            }
        }

        private static void ProcessDirectory(String directoryPath)
        {
            ProcessChildDirectory(directoryPath, "bin");
            ProcessChildDirectory(directoryPath, "obj");
            ProcessChildDirectory(directoryPath, "TestResults");
        }
    }
}

The best way to hook this up is via the Visual Studio External Tools dialog by passing in the current solutions directory path.

image

This method also allows you to output the console results to the Output window for a more integrated experience.

NOTE: It’s a good idea to run a Visual Studio clean from the build menu before running this tool to get Visual Studio to release any locks it has on files in these directories. We haven’t had any assembly version conflicts since running this tool.

You can either compile the above yourself or grab the executable below.

Neovolve.SolutionCleaner.zip (2.61 kb)

Tags:

Jul 27 2010

Tracking lazy loaded build trees in Unity

Category: .NetRory Primrose @ 08:31

I recently posted a Unity extension for disposing build trees created by Resolve and BuildUp actions. Unity has a feature that supports lazy loading injected dependencies that the original disposal extension didn’t cater for.

Consider the following example.

using System;
using Microsoft.Practices.Unity;
using Neovolve.Toolkit.Unity;

namespace Neovolve.LazyInjectionTesting
{
    class Program
    {
        static void Main(String[] args)
        {
            IUnityContainer container = new UnityContainer();

            container.AddExtension(new DisposableStrategyExtension());
            container.RegisterType(typeof(ITester), typeof(Tester));

            Root root = container.Resolve<Root>();

            container.Teardown(root);

            Console.WriteLine(root.TestInstance.IsDisposed);
            Console.ReadKey();
        }
    }

    public class Root
    {
        public Root(ITester tester)
        {
            TestInstance = tester;
        }

        public ITester TestInstance
        {
            get;
            private set;
        }
    }

    public interface ITester
    {
        void DoSomething();

        Boolean IsDisposed
        {
            get;
        }
    }

    public class Tester : ITester, IDisposable
    {
        public void DoSomething()
        {
        }

        public void Dispose()
        {
            IsDisposed = true;
        }

        public bool IsDisposed
        {
            get;
            private set;
        }
    }
}

This example resolves an instance of Root that has a dependency of type ITester. The build tree tracked by the disposal extension for this example is:

  • Root
    • Tester

Tester exposes a property that indicates whether the instance has been disposed. The disposal extension will ensure that all items in the build tree are disposed when the container is told to tear down the root instance. The Tester.IsDisposed property returns True when this console code is run.

Lazy loading dependencies is achieved by changing the injection type from T to Func<T>. This can be done in the above example by changing the Root constructor from public Root(ITester tester) to public Root(Func<ITester> tester). The example above now looks like the following. This delegate then needs to be invoked to get Unity to resolve the dependency instance.

using System;
using Microsoft.Practices.Unity;
using Neovolve.Toolkit.Unity;

namespace Neovolve.LazyInjectionTesting
{
    class Program
    {
        static void Main(String[] args)
        {
            IUnityContainer container = new UnityContainer();

            container.AddExtension(new DisposableStrategyExtension());
            container.RegisterType(typeof(ITester), typeof(Tester));

            Root root = container.Resolve<Root>();
            ITester testInstance = root.TestInstance();

            container.Teardown(root);

            Console.WriteLine(testInstance.IsDisposed);
            Console.ReadKey();
        }
    }

    public class Root
    {
        public Root(Func<ITester> tester)
        {
            TestInstance = tester;
        }

        public Func<ITester> TestInstance
        {
            get;
            private set;
        }
    }

    public interface ITester
    {
        void DoSomething();

        Boolean IsDisposed
        {
            get;
        }
    }

    public class Tester : ITester, IDisposable
    {
        public void DoSomething()
        {
        }

        public void Dispose()
        {
            IsDisposed = true;
        }

        public bool IsDisposed
        {
            get;
            private set;
        }
    }
}

Unity will create a delegate for Func<ITester> in order to call the constructor on Root. The delegate is a function that will resolve ITester from the container when the delegate is invoked. This means that the resolution of Root occurs at a different time to the resolution of ITester. The DisposableStrategyExtension is now tracking two build trees rather than one. The build tree that contains Root does not contain ITester and therefore the disposal strategy can’t dispose the dependency when container.TearDown(root) is invoked. The console application now returns False because the DisposalStrategyExtension does not understand that the two build trees are related.

I have updated the DisposableStrategyExtension to correctly track build trees of these lazy loaded dependencies.

The PostBuildUp method is the second half of the logic that creates a build tree for each Unity build operation in this extension. The update to track lazy loaded build trees is to detect that the dependency created (context.Existing) is a delegate. If this is the case then  a wrapper delegate is created and returned instead.

public override void PostBuildUp(IBuilderContext context)
{
    if (context != null)
    {
        // Check if the item created is Func<T> for lazy loaded dependency injection
        if (context.Existing is Delegate)
        {
            context.Existing = CreateTrackedDeferredResolution((Delegate)context.Existing);
        }

        AssignInstanceToCurrentTreeNode(context.BuildKey, context.Existing);

        BuildTreeItemNode parentNode = CurrentBuildNode.Parent;

        if (parentNode == null)
        {
            // This is the end of the creation of the root node
            using (new LockWriter(_lock))
            {
                BuildTrees.Add(CurrentBuildNode);
            }
        }

        // Move the current node back up to the parent
        // If this is the top level node, this will set the current node back to null
        CurrentBuildNode = parentNode;
    }

    base.PostBuildUp(context);
}

The wrapper delegate will now be injected as the dependency rather than the Unity delegate. The wrapper delegate is created using the CreateTrackedDeferredResolution method. This method has some defensive coding to ensure that we are actually dealing with a Func<T> delegate. The wrapper delegate it creates is a function call out to a Resolve method on a custom DeferredResolutionTracker<T> class.

public Delegate CreateTrackedDeferredResolution(Delegate originalDeferredFunction)
{
    Type delegateType = originalDeferredFunction.GetType();

    if (delegateType.IsGenericType == false)
    {
        return originalDeferredFunction;
    }

    Type genericDelegateType = delegateType.GetGenericTypeDefinition();

    if (genericDelegateType.Equals(typeof(Func<>)) == false)
    {
        return originalDeferredFunction;
    }

    // This looks like a lazy loaded delegate for dependency injection
    // We need to redirect this through another method to manage the original build tree 
    // when the delegate invocation creates more instances
    Type[] genericArguments = delegateType.GetGenericArguments();

    if (genericArguments.Length > 1)
    {
        return originalDeferredFunction;
    }

    Type genericArgument = genericArguments[0];
    Type deferredTrackerType = typeof(DeferredResolutionTracker<>);
    Type[] typeArguments = new[]
                                {
                                    genericArgument
                                };
    Type genericDeferredTrackerType = deferredTrackerType.MakeGenericType(typeArguments);
    MethodInfo resolveMethod = genericDeferredTrackerType.GetMethod("Resolve");
    Object[] trackerArguments = new Object[]
                                    {
                                        originalDeferredFunction, this, CurrentBuildNode
                                    };
    Object resolvedTracker = Activator.CreateInstance(genericDeferredTrackerType, trackerArguments);

    return Delegate.CreateDelegate(delegateType, resolvedTracker, resolveMethod);
}

The DeferredResolutionTracker class takes in the original delegate, the parent node in the original build tree (the instance that the delegate is injected into) and a reference to the collection of build trees. Its Resolve method then invokes the original delegate to lazy load the dependency instance from Unity. It then searches the collection of build trees to find the build tree of that resolution action. That build tree is then removed from the collection and added as a child of the original parent node from the original build tree.

using System;
using System.Diagnostics.Contracts;
using System.Linq;

namespace Neovolve.Toolkit.Unity
{
    internal class DeferredResolutionTracker<T>
    {
        public DeferredResolutionTracker(
            Func<T> resolutionFunction, IBuildTreeTracker originalTracker, BuildTreeItemNode parentNode)
        {
            Contract.Requires<ArgumentNullException>(resolutionFunction != null, "No resolution function provided.");
            Contract.Requires<ArgumentNullException>(originalTracker != null, "No original tracker provided.");
            Contract.Requires<ArgumentNullException>(parentNode != null, "No parent node provided.");

            ResolutionFunction = resolutionFunction;
            OriginalTracker = originalTracker;
            ParentNode = parentNode;
        }

        public T Resolve()
        {
            T resolvedInstance = ResolutionFunction();

            BuildTreeItemNode deferredBuildTree =
                    OriginalTracker.BuildTrees.Where(x => IsDeferredBuildTreeReference(x, resolvedInstance)).
                        FirstOrDefault();

            if (deferredBuildTree == null)
            {
                return resolvedInstance;
            }

            // We have found the deferred build tree for the instance created by the deferred resolution function
            OriginalTracker.RemoveBuildTree(deferredBuildTree);

            // Add the build tree as a child to the parent node
            ParentNode.Children.Add(deferredBuildTree);

            return resolvedInstance;
        }

        private static Boolean IsDeferredBuildTreeReference(BuildTreeItemNode buildTreeNode, T resolvedInstance)
        {
            if (buildTreeNode == null)
            {
                return false;
            }

            if (buildTreeNode.ItemReference.IsAlive == false)
            {
                return false;
            }

            if (ReferenceEquals(buildTreeNode.ItemReference.Target, resolvedInstance))
            {
                return true;
            }

            return false;
        }

        private IBuildTreeTracker OriginalTracker
        {
            get;
            set;
        }

        private BuildTreeItemNode ParentNode
        {
            get;
            set;
        }

        private Func<T> ResolutionFunction
        {
            get;
            set;
        }
    }
}

The extension will now have a build tree for the root instance from the example above that has a reference to the lazy loaded dependency. This means that the extension will now correctly tear down the root instance when container.TearDown(root) is invoked. The above example with this fix now writes True to the console for the lazy loaded example.

The updated code for the DisposalStrategyExtension can be found here in my Toolkit project on CodePlex.

Tags: ,

Jul 23 2010

Caching workflow activities to increase performance

Category: .NetRory Primrose @ 07:14

David Paquette posted last year about the performance characteristics of WF4. Runtime performance is a typical complaint with WF but it can be minimised as David has indicated. Adding some caching logic for workflow activity instances will avoid the expensive start-up process for invoking activities. Subsequent activity invocations will be much faster by getting the activity instance from the cache rather than creating a new one.

I’ve put together an ActivityStore class that handles this caching requirement.

using System;
using System.Activities;
using System.Collections.Generic;
using System.Threading;
using Neovolve.Toolkit.Threading;

namespace Neovolve.ActivityTesting
{
    internal static class ActivityStore
    {
        private static readonly IDictionary<Type, Activity> _store = new Dictionary<Type, Activity>();

        private static readonly ReaderWriterLockSlim _syncLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

        public static T Resolve<T>() where T : Activity, new()
        {
            Type activityType = typeof(T);

            using (new LockReader(_syncLock))
            {
                if (_store.ContainsKey(activityType))
                {
                    return _store[activityType] as T;
                }
            }

            using (new LockWriter(_syncLock))
            {
                // Protect the store against mutliple threads that get passed the reader lock
                if (_store.ContainsKey(activityType))
                {
                    return _store[activityType] as T;
                }

                T activity = new T();

                _store[activityType] = activity;

                return activity;
            }
        }
    }
}

This class will hold on to activity instances in a dictionary using the activity type as the key. To use this class you simply need to make a call out to ActivityStore.Resolve<T>() rather than new T() where T is your activity type.

Tags: ,

Jul 22 2010

Working with custom proxies

Category: .NetRory Primrose @ 07:56

My recent post about creating proxies with RealProxy provided an example for creating a custom proxy implementation. Using proxies can provide a lot of power and flexibility to an application. Most of this code is common plumbing code that can be refactored out into some reusable classes.

The ProxyHandler class below is the first of these reusable classes. It helps with creating RealProxy types by providing the common logic of method identification, exception processing and method response management. It also provides the support for a derived proxy implementation to leverage some initialization logic provided by the calling application. It uses a MethodResolver class from my Toolkit project to identify the method to invoke on the proxy.

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Security.Permissions;
using Neovolve.Toolkit.Reflection;
 
namespace Neovolve.Toolkit.Communication
{
    public abstract class ProxyHandler<T> : RealProxy where T : class
    {
        protected ProxyHandler()
            : base(typeof(T))
        {
        }

        public virtual void Initialize<TInitialize>(Action<TInitialize> action)
        {
            InitializeAction = action;
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
        [DebuggerStepThrough]
        public override IMessage Invoke(IMessage msg)
        {
            Debug.Assert(msg != null, "No message has been provided");

            ReturnMessage responseMessage;
            Object response = null;
            Exception caughtException = null;

            try
            {
                String methodName = (String)msg.Properties["__MethodName"];
                Type[] parameterTypes = (Type[])msg.Properties["__MethodSignature"];
                MethodBase method = MethodResolver.Resolve(typeof(T), methodName, parameterTypes);

                Debug.Assert(method != null, "Method was not found on the proxy");

                Object[] parameters = (Object[])msg.Properties["__Args"];

                // Invoke the action
                response = ExecuteMethod(method, parameters);
            }
            catch (Exception ex)
            {
                // Store the caught exception
                caughtException = ex;
            }

            IMethodCallMessage message = msg as IMethodCallMessage;

            // Check if there is an exception
            if (caughtException == null)
            {
                // Return the response from the service
                responseMessage = new ReturnMessage(response, null, 0, null, message);
            }
            else
            {
                // Return the exception thrown by the service
                responseMessage = new ReturnMessage(caughtException, message);
            }

            // Return the response message
            return responseMessage;
        }

        protected abstract Object ExecuteMethod(MethodBase method, Object[] parameters);

        protected MulticastDelegate InitializeAction
        {
            get;
            set;
        }
    }
}

The ProxyManager class below encapsulates the creation and lifetime management of a ProxyHandler instance. It creates a proxy instance from the ProxyHandler when the Proxy property is referenced and disposes the proxy when the ProxyManager is disposed. It has some logic for attempted to resolve a ProxyHandler<T> or then falling back on a default proxy or a proxy to a WCF channel if no ProxyHandler is provided in its constructor.

using System;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using Neovolve.Toolkit.Reflection;

namespace Neovolve.Toolkit.Communication
{
    public class ProxyManager<T> : IDisposable where T : class
    {
        private T _proxy;

        public ProxyManager()
        {
            if (TypeResolver.CanResolveType(typeof(ProxyHandler<T>)))
            {
                ProxyHandler = TypeResolver.Create<ProxyHandler<T>>();
            }
            else
            {
                // Check if T is a service contract
                Object serviceContract = typeof(T).GetCustomAttributes(true).Where(x => x is ServiceContractAttribute).FirstOrDefault();

                if (serviceContract != null)
                {
                    // This is a service contract, default to using the WCF proxy handler
                    ProxyHandler = new ChannelProxyHandler<T>();
                }
                else
                {
                    // No proxy handler is known for this type
                    ProxyHandler = new DefaultProxyHandler<T>();
                }
            }
        }

        public ProxyManager(ProxyHandler<T> proxyHandler)
        {
            ProxyHandler = proxyHandler;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(Boolean disposing)
        {
            if (disposing)
            {
                // Free managed resources
                if (Disposed == false)
                {
                    Disposed = true;

                    IDisposable disposableHandler = ProxyHandler as IDisposable;

                    if (disposableHandler != null)
                    {
                        disposableHandler.Dispose();
                    }

                    ProxyHandler = null;
                    Proxy = null;
                }
            }

            // Free native resources if there are any.
        }

        public T Proxy
        {
            get
            {
                if (Disposed)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }

                if (_proxy == null)
                {
                    // Create a channel from the handler
                    _proxy = (T)ProxyHandler.GetTransparentProxy();

                    Debug.Assert(_proxy != null, "The proxy handler failed to create the proxy.");
                }

                return _proxy;
            }

            private set
            {
                _proxy = value;
            }
        }

        public ProxyHandler<T> ProxyHandler
        {
            get;
            private set;
        }

        protected Boolean Disposed
        {
            get;
            set;
        }
    }
}

These classes work together to make it really easy to work with custom proxies. The most common usage I have for these classes is to proxy a call out to a WCF service. The following is an example of how this looks in a client console application. The benefit here for working with WCF is that all the management of WCF channels is abstracted away from the application code.

using System;
using System.ServiceModel;
using Neovolve.Toolkit.Communication;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ProxyManager<ITestService> manager = new ProxyManager<ITestService>())
            {
                String result = manager.Proxy.DoSomething("Service input data");

                Console.WriteLine("Result from service is: " + result);
            }

            Console.ReadKey();
        }
    }

    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        String DoSomething(String data);
    }
}

The code for these classes can be found in my Neovolve.Toolkit project out on CodePlex.

Tags:

Jul 20 2010

Unity Injection With ASP.Net and WCF - Presentation deck and code

Category: .Net | IT RelatedRory Primrose @ 08:25

Yesterday I ran a couple of sessions at the Canberra .Net users group. I have attached a zip of the presentation deck and demo projects for you to have a look at in your own time.

Unity Injection With ASP.Net and WCF.zip (1.45 mb)

Tags: , ,