locked
The preferred way of obtaining states of all activities in a WF? RRS feed

  • Question

  • Hello,

    I have a requirement to display the states of activities within an executing workflow while maintaining the hierarchy of the activities in my display (eg: a tree). Is there a simple way to take a WF/Activity instance Guid and obtain the states for each of the activities within it? Right now I am using a tracker to store the latest state for activities and then providing the ability to generate a 'state tree' for that tracker. It'd be much better IMO if I didn't have to keep track of state history itself, and instead used a WWF method to get a state snapshot of a given activity at any time... Does such a method exist?

    Here is what I am currently using:

     public class ActivityStateTree
      {
        private List<ActivityStateTree> m_Children = new List<ActivityStateTree>();
    
        private ActivityStateTree(Activity activity, string latestState)
        {
          Activity = activity;
          LatestState = latestState;
        }
    
        public Activity Activity
        {
          get;
          private set;
        }
    
        public string LatestState
        {
          get;
          private set;
        }
    
        public ActivityStateTree[] ChildTrees
        {
          get { return m_Children.ToArray(); }
        }
    
        static internal ActivityStateTree BuildStateTree(Activity activity,
          StateTrackingParticipant stateTracker)
        {
          if (activity == null)
          {
            throw new ArgumentNullException("activity");
          }
    
          if (stateTracker == null)
          {
            throw new ArgumentNullException("stateTracker");
          }
    
          // Get the activities latest state, and then build the root tree:
    
          string latestState = stateTracker.GetLatestStateForActivity(activity);
          if (latestState == null)
          {
            latestState = "None";
          }
    
          ActivityStateTree tree = new ActivityStateTree(activity, latestState);      
          
          // Now get the children
    
          var children = WorkflowInspectionServices.GetActivities(activity);
          var enumerator = children.GetEnumerator();
          while (enumerator.MoveNext())
          {        
            Activity childActivity = enumerator.Current;
            
            if (childActivity.GetType().Namespace.StartsWith("System.Activities.Expressions")
              || childActivity.GetType().Namespace.StartsWith("Microsoft.VisualBasic.Activities"))
            {
              // This is an expression or visual basic assignment, so don't include it in our tree.
              continue;
            }
    
            ActivityStateTree childTree = BuildStateTree(enumerator.Current, stateTracker);
            tree.m_Children.Add(childTree);
          }
    
          return tree;
        }
    
      }
    
    
    
    public class StateTrackingParticipant : TrackingParticipant
      {
        private Dictionary<string, ActivityStateRecord> m_LatestActivityStates =
          new Dictionary<string, ActivityStateRecord>();
    
        public StateTrackingParticipant() { }
    
        protected override void Track(TrackingRecord record, TimeSpan timeout)
        {
          ActivityStateRecord aRecord = record as ActivityStateRecord;      
    
          if (aRecord != null)
          {
            m_LatestActivityStates[aRecord.Activity.Id] = aRecord;
    
            Action<ActivityStateRecord> changeSubscriber = OnStateChange;
            if (changeSubscriber != null)
            {
              changeSubscriber(aRecord);
            }        
          }
        }
    
        public Action<ActivityStateRecord> OnStateChange;
        
        public string GetLatestStateForActivity(Activity activity)
        {
          if (!m_LatestActivityStates.ContainsKey(activity.Id))
          {
            return null;
          }
    
          return m_LatestActivityStates[activity.Id].State;
        }
      }
    

    Thursday, August 5, 2010 8:51 PM

Answers

All replies

  • ... Anyone?
    Tuesday, August 10, 2010 12:29 AM
  • Creating the TrackingPartecipant is the best way on doing it.

    You may also want to persist the status of any workflow instance directly on a database and perform queries/statistics against it. Depending on your implementaiton you may also think about having any long-running activity, as well as the user closing your interface and re-opening it; in this case persistence is not optional. 

    This way, your tracking partecipant writes on a database, and your UI will read from there the current status of any running workflow.

    Hope it helps,


    Adriano
    Tuesday, August 10, 2010 7:38 AM
  • Hi,

    Visual Workflow Tracking sample from MSDN could be helpful to you;
    http://msdn.microsoft.com/en-us/library/ee624139.aspx

    And a blog article about;
    http://blogs.msdn.com/b/kushals/archive/2009/12/22/visualworkflowtracking-aka-workflowsimulator.aspx

    Regards
    This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft Online Community Support. My Blog:http://xhinker.com
    • Marked as answer by Andrew_Zhu Friday, August 13, 2010 2:02 AM
    Tuesday, August 10, 2010 8:45 AM