Creating Parallel Tasks from a SharePoint 2010 Workflow

SharePoint 2010

SharePoint Visual How To

Summary:  Learn how to create parallel Microsoft SharePoint 2010 tasks in a Microsoft Visual Studio 2010 workflow project.

Last modified: September 12, 2012

Applies to: SharePoint Foundation 2010 | SharePoint Server 2010 | Visual Studio | Visual Studio 2008 | Visual Studio 2010

Provided by:  Scot Hillier, Microsoft SharePoint MVP

Overview

A task is a key component of any Microsoft SharePoint 2010 workflow. Your workflow might need to assign and track parallel tasks. You can create parallel SharePoint tasks from a Microsoft Visual Studio 2010 workflow project.

Code It

To create parallel tasks in a workflow, you must use a ParallelActivity activity in the workflow.

Creating the Workflow

When you create parallel tasks in a SharePoint workflow, begin by creating the tasks outside the ParallelActivity activity. Then, use a ParallelActivity activity to track when each parallel task is changed or completed. Figure 1 shows the complete workflow with two parallel tasks.

Figure 1. Workflow with parallel tasks

Workflow with parallel tasks
namespace ParallelTasks
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        public Workflow1()
        {
            InitializeComponent();
        }

        public Guid workflowId = default(System.Guid);
        public SPWorkflowActivationProperties workflowProperties = 
          new SPWorkflowActivationProperties();
        public Guid task1Id = default(System.Guid);
        public SPWorkflowTaskProperties task1Properties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public Guid task2Id = default(System.Guid);
        public SPWorkflowTaskProperties task2Properties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public bool task1Complete = false;
        public bool task2Complete = false;
        public SPWorkflowTaskProperties task1AfterProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties task1BeforeProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties task2AfterProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties task2BeforeProperties = 
          new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public Guid TaskStatusFieldId = 
          new Guid("c15b34c3-ce7d-490a-b133-3f4de8801b76");
        public String task1Outcome = default(System.String);
        public String task2Outcome = default(System.String);

        private void onWorkflowActivated1_Invoked(object sender, 
          ExternalDataEventArgs e)
        {
            // Save the workflow ID.
            workflowId = workflowProperties.WorkflowId;
        }

        private void createTask1_MethodInvoking(object sender, 
          EventArgs e)
        {
            // Create the first task.
            SPUser approver1 = 
              GetUserFromPickerString(workflowProperties.Item
                ["Team Leader"].ToString());
            SPUser employee = 
              GetUserFromPickerString(workflowProperties.Item
              ["Employee"].ToString());
            task1Id = Guid.NewGuid();
            task1Properties.AssignedTo = approver1.LoginName;
            task1Properties.Description = 
              "Approve Vacation Request for " + employee.Name;
            task1Properties.Title = "Vacation Request Approval";
        }

        private void createTask2_MethodInvoking(object sender, 
          EventArgs e)
        {
            // Create the second task.
            SPUser approver2 = 
              GetUserFromPickerString(workflowProperties.Item
              ["Department Head"].ToString());
            SPUser employee = 
              GetUserFromPickerString(workflowProperties.Item
              ["Employee"].ToString());
            task2Id = Guid.NewGuid();
            task2Properties.AssignedTo = approver2.LoginName;
            task2Properties.Description = 
              "Approve Vacation Request for " + employee.Name;
            task2Properties.Title = "Vacation Request Approval";
        }

        private void task1NotComplete(object sender, 
          ConditionalEventArgs e)
        {
            e.Result = !task1Complete;
        }

        private void task2NotComplete(object sender, 
          ConditionalEventArgs e)
        {
            e.Result = !task2Complete;
        }

        private void onTaskChanged1_Invoked(object sender, 
          ExternalDataEventArgs e)
        {

            // Check whether task 1 is completed.
            string taskStatus = 
              task1AfterProperties.ExtendedProperties
              [TaskStatusFieldId].ToString();
            if (taskStatus.Equals("Completed"))
                task1Complete = true;
            else
                task1Complete = false;
        }

        private void onTaskChanged2_Invoked(object sender, 
          ExternalDataEventArgs e)
        {

            // Check whether task 2 is completed.
            string taskStatus = 
              task2AfterProperties.ExtendedProperties
              [TaskStatusFieldId].ToString();
            if (taskStatus.Equals("Completed"))
                task2Complete = true;
            else
                task2Complete = false;
        }

        private void completeTask1_MethodInvoking(object sender, 
          EventArgs e)
        {
            // Finalize task 1.
            task1AfterProperties.PercentComplete = 100;
            task1Outcome = "Reviewed";
        }

        private void completeTask2_MethodInvoking(object sender, 
          EventArgs e)
        {
            // Finalize task 2.
            task2AfterProperties.PercentComplete = 100;
            task2Outcome = "Reviewed";
        }

        private SPUser GetUserFromPickerString(string PickerString)
        {
            string id = string.Empty;
            try
            {
                id = PickerString.Substring(0, 
                  PickerString.IndexOf(';'));
                return workflowProperties.Web.SiteUsers.GetByID
                  (int.Parse(id));
            }
            catch { return null; }
        }
    }
}
Read It

When you create parallel tasks in a SharePoint workflow, you must first use the CreateTask activity to create tasks. Then you can use the ParallelActivity activity to track when the tasks are changed or completed.

Following is a review of the activities:

  • The CreateTask activity creates a new task in a SharePoint list.

  • The OnTaskChanged activity checks whether the task is complete each time a user changes the task in some way.

  • The CompleteTask activity finishes the task and allows the workflow to continue.

  • The ParallelActivity activity causes the tasks to run in parallel so that they can be completed in any order.

See It

Watch the video

Watch video

Length: 00:07:34

 

Explore It

About the Author

Scot Hillier is an independent consultant and Microsoft SharePoint Most Valuable Professional (MVP) focused on creating solutions for Information Workers with SharePoint, Office, and related .NET Framework technologies. He is the author/coauthor of 15 books and DVDs on Microsoft technologies, including Inside Microsoft SharePoint 2010 and Professional Business Connectivity Services. Scot splits his time between consulting on SharePoint projects, speaking at SharePoint events like Tech-Ed, and delivering training for SharePoint developers. Scot is a former U.S. Navy submarine officer and graduate of the Virginia Military Institute. Scot can be reached at scot@shillier.com.

Show: