Sep 8, 2009

HelloWorld Workflow Exercise

The task is creating a workflow that requests for a name (2 to 3 chars long) from the console and prints it, saying hello.

Creating a new VS2010 workflow Flowchart console application crashes first time, but restarting allows continuing.

We create a FlowChart workflow with a DoWhile activity, create a ReadlineActivity

image

image

assign the result of the code activity (string) to workflow variable (id):

image

press “F9” to add breakpoint in workflow designer and run it with “F5”:

Enter name:
l
Enter name:
leder
Enter name:
lem
Hello lem from WF4.0
Press any key to continue . . .

Now, we want to implement best practices and don’t block in an activity, so let’s refactor it to run asynchronous.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Threading.Tasks;

namespace HelloWorldWorkflow
{
    /// <summary>
    /// Asynchronous code activity that does the bookmark plumbing code correctly.
    /// </summary>
    /// <typeparam name="T">Type of the return value.</typeparam>
    public abstract class AsyncCodeActivity<T> : CodeActivity<T>
    {
        /// <summary>
        /// Activity execution method.
        /// </summary>
        /// <param name="context">The code activity context.</param>
        protected override void Execute(CodeActivityContext context)
        {
            var asyncContext = context.SetupAsyncOperationBlock();
            var task = new Task((ac) =>
            {
                var asyncCtx = (AsyncOperationContext)ac;

                T ret = InternalExecute(context);

                asyncCtx.CompleteOperation(new BookmarkCallback(InternalCompleteAsyncWork), ret);
            }, asyncContext);
            task.Start();
        }

        /// <summary>
        /// Internal activity execution method.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        protected abstract T InternalExecute(CodeActivityContext context);

        /// <summary>
        /// Internal async code activity completion method.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="bm"></param>
        /// <param name="ret"></param>
        protected virtual void InternalCompleteAsyncWork(ActivityExecutionContext ctx, Bookmark bm, object ret)
        {
            Result.Set(ctx, ret);
        }
    }
}

and my ReadlineActivity would look like this:

public class ReadlineActivity : AsyncCodeActivity<string>
{
    protected override string InternalExecute(System.Activities.CodeActivityContext context)
    {
        Console.Write("Enter name: ");
        string id = Console.ReadLine();
        return id;
    }
}

Much easier and less error prone!

No comments:

Post a Comment