ActivityExecutionStatus Executing to Closed
I have created a simple Custom Activity and overridden the protected method Execute.
The nature of job within Execute is such that the response would arrive into the activity asynchronously, I am returning ActivityExecutionStatus.Executing at the end of the method.
I have a delegate callback
private void myCallBackMethod(object Sender, EventArgs Args).
My callback gets called successfully on recieving the response. What I do not understand now is, how and where do I return ActivityExecutionStatus.Closed so that the workflow having this CustomActivity knows that the activity is completed and it can proceed with the rest of the activities.
In my case I will need the workflow execution to wait until the CustomActivity is completed, but since I have a call back within my CustomActivity I cannot return Closed from Execute method and I dont think I can return Closed from callback.
Currently my workflow is hung once I get into this CustomActivity since the workflow is waiting for completion signal from the activity.
Appreciate any help on this.
Thanks.
[1084 byte] By [
SolveIt] at [2007-12-23]
I made a mistake replying in a rush...
Execute method needs some changes as I forgot to add registration for event
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
if
(EnabledActivities.Count == 0)return ActivityExecutionStatus.Closed;Activity nextActivity = this.activityIndex < this.EnabledActivities.Count
? this.EnabledActivities[this.activityIndex++]
: null;
if (nextActivity == null)
return ActivityExecutionStatus.Closed;
else
{
nextActivity.RegisterForStatusChange(
Activity.ClosedEvent, this);executionContext.ExecuteActivity(nextActivity);
return ActivityExecutionStatus.Executing;}
}
OnEvent method looks like this
public
void OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e){
ActivityExecutionContext context = sender as ActivityExecutionContext;Activity closedActivity = e.Activity;closedActivity.UnregisterForStatusChange(
Activity.ClosedEvent, this);Activity nextActivity = this.activityIndex < this.EnabledActivities.Count? this.EnabledActivities[this.activityIndex++]
: null;
if (nextActivity == null || e.ExecutionResult == ActivityExecutionResult.Faulted)
{
context.CloseActivity();
}
else
{
nextActivity.RegisterForStatusChange(
Activity.ClosedEvent, this);context.ExecuteActivity(nextActivity);
}
}
Thanks for the help.
I will really appreciate if I can have the following clarifications so I can understand the code better.
1. What are activityIndex and EnabledActivities.Count? Do I need to maintain these in the activity code?
2. I will know that the ExecutionStatus can be set to Closed only in the Callback that I referred in my post. So how do I translate that to triggering of Event?
3. Just because I want to set the execution status to Closed in a Callback function do I need to take control of Workflow sequence and call the next activity execution through code?
I am sorry if the questions are dumb, but I am really confused.
Appreciate if there are clarifications and sorry for the trouble.
Thanks.
Hi,
why don't you delegate your long running task to the host by using the local service pattern ?
2 ways :
1.way:
1.1 in your custom sequenceActivity, use an ExternalMethod Activity that call a method running (as a service) in the host
1.2 this sequence activity can be followed by an WaitForExternalEvent Activity
2nd way: (my preferred)
take a look at Paul Andrew's sample here . This sample illustrates how to achieve way 1 in a single activity
-2.1 Create a queue in your Execute Method and return ActivityExecutionStatus.Executing
-2.2 Add an event handler that will notify your activity that an item has been queued
-2.3 The (host)service enqueues a value
-2.4 Your event handler is notified, retrieves the value, deletes the queue and closes the activity
Here are the main methods
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context){
string qName = this.QualifiedName + "ResultQueue";WorkflowQueuingService qServ = context.GetService<WorkflowQueuingService>();WorkflowQueue q = qServ.CreateWorkflowQueue(qName, false);q.QueueItemAvailable += OnItemAvailable;
FactoringService factServ = context.GetService<FactoringService>();factServ.FactorPrimes(qName);
return ActivityExecutionStatus.Executing;}
//// This is called on the workflow thread when the prime factoring is complete// and the queue message is received//private void OnItemAvailable(object sender, QueueEventArgs e){
ActivityExecutionContext context = sender as ActivityExecutionContext;WorkflowQueuingService qServ = context.GetService<WorkflowQueuingService>();WorkflowQueue q = qServ.GetWorkflowQueue(e.QueueName);result = (
int)q.Dequeue();qServ.DeleteWorkflowQueue(e.QueueName);
context.CloseActivity();
}
Serge