Dominik Mauchle

When using the CustomActivityFramework sample (http://wf.netfx3.com/files/folders/activity_behavior/entry838.aspx), I noticed that rehydrating the workflow does not work properly. I have the following scenario:

1. The workflow is currently waiting for a file being created on the "Event1" activity (a FileSystemEvent activity)

2. I stop the wf host.

3. I run the host again, only starting the runtime, not loading a new workflow

The file system is no longer being watched, the Event1 activity is not active.

I tested the same scenario with a HandleExternalEvent Activity, and it works there.

I guess, the problem ist that the FileSystemEvent activity does not use the ExternalDataExchange mechanism, so the event handlers are not being reattached.

What steps would be necessary to build the rehydrating process into the FileSystemEvent activity I'm interested in this topic because I plan to use my own IEventActivity-derived Activities, since this allows for tighter control of the process. I would be very glad if someone could give me a clue.



Re: Windows Workflow Foundation CustomActivityFramework sample and Persistence

Tom Lake - MSFT

The reason for this behavior is the way the sample activity was written. The FileSystemEventService is the one that registers for the FileSystemWatcher events. This means when the host is restarted you will need to re-register for the events or you won¡¯t get notification.






Re: Windows Workflow Foundation CustomActivityFramework sample and Persistence

robwf

Can you elaborate on that explanation I'm running into the same problem. It's not really about reregistring at the "host" level as you say - it's re-registering at each of the InputActivities. Therefore, where in the InputActivity base do you recommend re-registering



Re: Windows Workflow Foundation CustomActivityFramework sample and Persistence

R__Rennie

I think I might have found a way around this, and maybe this can be updated in the InputActivity, but I did it in my derivative in any event. Please let me know if this is not the "right" way. My case is, specifically, I have a Dictionary<Guid,Subscription> in my local service which records a subscription id -> (workflow instance id, queuename) mapping. On Execute(), my custom InputActivity derivative registers as a listener with the local service. Thus, if the local service (i.e. the host) is shut down and then restarted, the InputActivity stops working because my external event is not reset.

To fix this, I simply overrode the OnActivityExecutionContextLoad() method in my custom InputActivity (i.e. in the derivative) and then reregistered as a listener based on the activity's ExecutionStatus and EventSubscriptionId. Since EventSubscriptionId is set when the listener is registered, this is used to check if we need to reregister. Note, this also required fixing the UnregisterListener in the InputActivity derivative.

InputActivity derivative code:

private void UnregisterListener(ActivityExecutionContext context)
{
MyWorkflowService wfService = context.GetService<MyWorkflowService>();
wfService.UnregisterListener(this.EventSubscriptionId);
this.EventSubscriptionId = Guid.Empty;
}

protected override void OnActivityExecutionContextLoad(IServiceProvider provider)
{
base.OnActivityExecutionContextLoad(provider);

if (ExecutionStatus == ActivityExecutionStatus.Executing ||

ExecutionStatus == ActivityExecutionStatus.Initialized )
{
MyWorkflowService wfService =
(MyWorkflowService)provider.GetService(typeof(MyWorkflowService));

if (wfService == null)
throw new ApplicationException("MyWorkflowService is not available.");

wfService.ReregisterListener(this.EventSubscriptionId, this.WorkflowInstanceId, this.QueueName);
}
}

Then, "ReregisterListener" in the localservice checks to see if the event subscription id is not already registered and is not Guid.Empty, and will reregister it if both are (i.e. not) true.

So, it's basically the same as the "SubscribeExternalEvent()" method, except IServiceProvider is used instead of the execution context.





Re: Windows Workflow Foundation CustomActivityFramework sample and Persistence

Tom Lake - MSFT

That might be one way of accomplishing the task, another would be to have the service be a WorkflowRuntimeService and override the OnStopped and OnStarted methods, for more information on workflow runtime services go to http://msdn2.microsoft.com/en-us/library/system.workflow.runtime.hosting.workflowruntimeservice.aspx. In the OnStopped method, or when the registration is made, persist the information needed to re-register the listeners and in the OnStarted method do that re-registering with the persisted data.




Re: Windows Workflow Foundation CustomActivityFramework sample and Persistence

R__Rennie

Agreed. That is another way to do it. I was looking for a way to NOT have to persist any information that the local service is keeping. I want to be able to right-click end task (in Task Manager), the host process and still be pretty much guaranteed a restart will regenerate what it needs in memory. With my workflows being persisted on idle, this is generally the case (save a small sliver of time window).

If I instead wait/rely on the runtime to notify my service on shutdown, I now need to create a service subscription dictionary persistence mechanism, as well as hope and pray that my OnStopped always gets called by the runtime in even E_UNEXPECTED circumstances ;-)

Thanks for the note though.