| Julius's profileJulius Ganns . netzkernPhotosBlogNetwork | Help |
|
August 26 WorkflowRegistry - A good friend and helperToday I want to make a short trip to WF and how I used it in a current project. It is the same project I've blogged about in my last post and we're talking again about a windows service that runs a lot of asynchronous tasks. This windows service exposes its functionality as a service to others components that by this means do not have to deal with all the asynchronous, synchronization and evaluation stuff.
The service calls two external web services in parallel on their own threads. In the past we did this using pure C# code and asynchronous delegates but as the logic became more and more complex we switched to WF to handle the complexity in a more convenient way.
We created a master workflow and two child workflows that perform the requests to the external services. The main workflow receives the outcome of both and performs some evaluation of the reponses, before it returns to the main thread. The child requests are called using the "InvokeWorkflow" activity in the master workflow.
Our goal was the following execution model:
Service Thread: Receive the request from another component and start the master workflow
Service Thread: Wait for the master workflow to complete
Master Workflow Thread: Perform some validation
Master Workflow Thread: Start the First and the Second Child Thread asynchronously
Child Threads (Sub-Workflows): Do the work side by side
Master Workflow Thread: Wait for the First and Second Child Thread to complete
Master Workflow Thread: Perform some evaluation and return to the Service Thread
Service Thread: Read the response from the Master Workflow Thread and return it to the component
Because we want the child threads to run simultaneously, we couldn't use the ManualWorkflowSchedulerService for the master workflow. By using it our child workflows would have been executed on the same thread as the master workflow and by that means in a row instead of in parallel on their own threads.. A solution to that problem could be to create an additional WorkflowRuntime without a manual scheduler service and let the child services run on that, but that hadn't solve our problem in the master workflow to wait for the completion of the child workflows.
Of course the WF infrastructure has the ability to provide the application with some execution status of all running workflows, but only if the workflow runtime has a persistence service in place. Because our workflows only have a very short lifetime, a persistence service was to much overhead and so we decided not to use it.
Essentially what we want to do is to have some kind of function like "WaitForWorkflowStatus(instanceId, status)" in the master workflow to wait for the child workflows and in the service thread to wait for the completion of the master workflow. So I wrote it.
The netzkern.Workflow.WorkflowRegistry is a static helper class that has some additional functions to help you deal with WF. First of all it is a static factory for a WorkflowRuntime. The runtime is internally prepared, started and some events are registered that allows the WorkflowRegistry to give every application a more convenient access to some features of WF.
First of all it exposes a function called RegisterCallback(instanceId, delegate) for registering a callback. By using it one can register a special callback just for a special workflow instead of registering for every workflow event through the use of WorkflowRuntime events.
Additionally it has the static function GetState(insanceId) that returns a WorkflowState object and provides access to the running workflow instance and a property called Status to read the current workflow status even if there is not persistence service registered in the worklfow runtime.
Last but not least it has a function to wait for a special status to occure on a executing workflow while blocking the current thread as long as the workflow does not have that status. This function made is possible for us to write the following two lines of code after invoking the external child workflows using the InvokeWorkflow activity:
WorkflowRegistry.WaitForWorkflowStatus(InvokeChildWorkflowOneActivity.InstanceId, WorkflowRegistry.Status.Complete);
WorkflowRegistry.WaitForWorkflowStatus(InvokeChildWorkflowTwoActivity.InstanceId, WorkflowRegistry.Status.Complete);
Internally the WorkflowRegistry uses an AutoResetEvent in a thread-safe manner to wait for the workflow to enter the requested status by blocking the running thread as long as necessary.
I will post the source code soon. |
|
|