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
assign the result of the code activity (string) to workflow variable (id):
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