Caching workflow activities to increase performance
Posted on July 23, 2010
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.