Welcome to SpellCoder Sign in | Join | Help

Parallel Event Handling in Windows Workflow

I've been using Windows Work Flow (WF) for a while, and I faced a lot of problems that I could solve, and this article is about one of them,
I am working on a project that faced the situation which I need to raise the same event to more than one HandleExternalEventActivity activities working in parallel, and I wanted just one of the HandleExternalEventActivity's to handle the coming event according to an identifier that I'm going to send with the EventArgs.
The problem comes, that by default, if you have a ParallelActivity and inside each branch you have a HandleExternalEventActivity activity, when you raise the event from the host, you can't control which HandleExternalEventActivity gets the event, so the most left HandleExternalEventActivity gets and handles the event before the other even if I wasn't targeting it in the first place.
So how to solve this,
after some searching and reading some working or sometimes old & not-working samples, I found out something called Correlation.
so as I could understand, Correlation is how you specify a parameter in the ExternalDataExchange that is going to identify who is going to handle the Event, and only the HandleExternalEventActivity that has the same parameter in its CorrelationToken will handle the event.
so it first sounds like a big blah blah blah blah.
but after some trials I managed to write some steps of how you do that.
1- Write your custom ExternalDataEventArgs by inheriting from ExternalDataEventArgs

[Serializable]
internal class TaskEventArgs : ExternalDataEventArgs
{
private string _identifier;

public string Id
{
get { return _identifier; }
set { _identifier = value; }
}

public TaskEventArgs(Guid instanceId): base(instanceId)
{

}
}
2- Write your ExternalDataExchange interface like this

[ExternalDataExchange]
[CorrelationParameter("Identifier")]
internal interface IService
{
[CorrelationInitializer]
void
Initialize(string Identifier);

[CorrelationAlias("Identifier", "e.Id")]
event EventHandler<TaskEventArgs> TaskFinished;
}

as you can see, we used three different Attributes
CorrelationParameter: this is where you specify the name of the parameter that will hold the value that Identifies the event destination
CorrelationInitializer: this is where you are going to specify the correlation parameter value, the CorrelationParameter should be a parameter to this method, and take care to write it exactly as you wrote it in the CorrelationParameter attribute with the same casing.
CorrelationAlias: this is where you specify the location of the parameter in the event arguments, because as we said before, the event argument will hold the destination identifier.

3- Implement the IService Interface
internal class Service:IService
{
#region IService Members

public void Initialize(string Identifier)
{
// Actually you don't need to do anything here; } public event EventHandler<TaskEventArgs> TaskFinished;

#endregion public void RaiseEvent(Guid instanceId, string identifier)
{
//initializing the TaskEventArgs. TaskEventArgs args = new TaskEventArgs(instanceId);
args.Id = identifier; // setting the specified identifier to the Id property in the TaskEventArgs. if (TaskFinished != null)
TaskFinished(null, args); // Firing the event } }
4- Now go to your Workflow designer, and add in every Parallel branch a CallExternalMethodActivity before the HandleExternalEventActivity you already have.
your workflow should look similar to this

as you can see in every branch you have a CallExternalMethodActivity, and HandelExternalEventActivity.
forget about the other two code activities right now.
5- Now configure the first CallExternalMethodActivity, in our case InitializeFirst
5.1 set the interface type to your ExternalDataExchange interface, in our case the IService interface
5.2 set the Method Name to the method that has the CorrelationInitializer attribute, in our case the Initialized Method in IService.
5.3 now you will notice that you have another option in the properties of the CallExternalMethodActivities called CorrelationToken, write a name inside this box "C1" for example and then expand the node by clicking on the + sign beside the CorrelationToken text and set the OwnerActivityName property with the name of Activity that holds the CallExternalMethodActivity, in our case it is sequenceActivity1.
5.4 also you will find the parameter of the Method you are calling shown in the property grid, in our case it is Identifier, set it to the identifier value you want, or bind it to a member of property, in our case we will bind it to the string "First"
5.4 repeat the same settings for the second CallExternalMethodActivity, in our case InitializeSecond but use different name for the CorrelationToken "C2" with OwnerActivityName to sequenceActivity2
the property grid should look similar to this

6- Configure the HandleExternalEventActivity, in our case HandleFirst
6.1 Choose the interface type as same as the one in the CallExternalMethod, in our case IService interface
6.2 Choose the Event Name, in our case TaskFinished
6.3 You will find a property CorrelationToken appeared, choose "C1" from the list you have
6.4 Repeat this settings for all other HandleExternalEventActivities you have, in our case HandleSecond but use the C2 CorrelationToken for this one.
The Property Grid of the HandleExternalEventActivity should look similar to this

7 now you are almost done, just go to the workflow creation code, usually in the Program.cs file and add an ExternalDataExchangeService to the runtime and add an instance of the IService service to it like this
ExternalDataExchangeService exchange = new ExternalDataExchangeService();
workflowRuntime.AddService(exchange);
Service service = new Service();
exchange.AddService(service);
Then after you start the instance and the runtime, you can start raising the event by using (in our case) RaiseEvent function and specify the Identifier you are targeting as a parameter to the function like this
service.RaiseEvent(instance.InstanceId, "First");
also for a complete example, I attached the complete version of the last code with this blog post. with enough documentation in the code.
Have fun coding.
kick it on DotNetKicks.com
Published Monday, October 02, 2006 5:00 AM by Mohammed Hossam
Filed Under: ,
Attachment(s): CorrelationExample.zip

Comments

# re: Parallel Event Handling in Windows Workflow

Saturday, October 07, 2006 9:37 AM by Hisham Abd El Hafez
it is really nice work in ur blog ya mohammed, Go ON Bashmohandes ;)

# re: Parallel Event Handling in Windows Workflow

Tuesday, October 17, 2006 4:14 AM by LLuis
Finally, a simple article that shows us how to do  an useful thing with WWF and not tries us to introduce again in the world of wwf.

# re: Parallel Event Handling in Windows Workflow

Thursday, January 11, 2007 9:58 AM by Max
Ok, but what OwnerActivityName properties are for? How WWF uses it?

# re: Parallel Event Handling in Windows Workflow

Saturday, January 27, 2007 3:08 PM by Prasad Rajagopal
Nice article ane nice work.

But I think you forgot to mention one important thing about the settings for the second branch. The CallExternalMethod in the second branch can't have the same settings as the first. Two of those properties needs to be different. The "CorrelationToken" name (which you have correctly mentioned) and "Identifier" value (which you didn't mention). I could not get it to working when I used "First" as the value for Identifier in both the branches. When i used "Second" for the identifier value in the second branch's callexternalMethod activity it works great.


Cheers,

Prasad Rajagopal

# re: Parallel Event Handling in Windows Workflow

Monday, April 02, 2007 8:05 AM by Ruurd Boeke
This is really great, however, it will not work in a state workflow, because the first activity (Setting the correlation token) is not a IEventactivity.

Any solutions?

# re: Parallel Event Handling in Windows Workflow

Monday, April 02, 2007 6:41 PM by Mohammed Hossam
I didn't use the State workflows so far, so I don't have a solution for the problem you are facing right now, sorry :(

# re: Parallel Event Handling in Windows Workflow

Saturday, April 07, 2007 3:18 AM by gaonian
you can add a Delay Activity as the first activity

# re: Parallel Event Handling in Windows Workflow

Friday, April 20, 2007 3:06 AM by Jindal
Nice R&D.
Also the similiar stuff is done in LAB -05 of WF hands-on Labs.
But definately explanation is much better in this blog.

Can anyone Pls. let me know where I can get the details of internal workings of WWF. What is happening behind the scene sort of stuff?

# re: Parallel Event Handling in Windows Workflow

Friday, April 20, 2007 2:04 PM by Mohammed Hossam
@Jindal
Thanks for you visit,
I think Windows Vista SDK has good stuff also, you can check it out
Anonymous comments are disabled