spacer
Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Sign in | Join | Help
  • Home
Mike Taulty's Blog » WF - "CallExternalMethod", "HandleExternalEvent"
WF - "CallExternalMethod", "HandleExternalEvent"
Mike Taulty's Blog
  • Home
  • About
  • Contact

Feeds

  • RSS for Posts
  • Atom

Mike's Badges

spacer
spacer
spacer
spacer
spacer

Tag Cloud

  • .NET
  • .NET Framework 4.0
  • ADO.NET
  • C#
  • Data Access
  • Data Services
  • Entity Framework
  • Hardware
  • LINQ
  • Live Framework
  • Mesh
  • Off Topic
  • Parallel Extensions
  • Silverlight
  • SQL Server
  • UK Communities
  • Visual Studio
  • WCF
  • Web Services
  • Windows 7
  • Windows Azure
  • Windows Live
  • Windows Vista
  • WPF
  • XML
View more

Blog Archive List

  • October 2009 (8)
  • September 2009 (8)
  • August 2009 (7)
  • July 2009 (10)
  • June 2009 (18)
  • May 2009 (11)
  • April 2009 (21)
  • March 2009 (35)
  • February 2009 (15)
  • January 2009 (20)
  • December 2008 (7)
  • November 2008 (19)
  • October 2008 (33)
  • September 2008 (31)
  • August 2008 (12)
  • July 2008 (22)
  • June 2008 (18)
  • May 2008 (18)
  • April 2008 (18)
  • March 2008 (23)
  • February 2008 (21)
  • January 2008 (31)
  • December 2007 (32)
  • November 2007 (27)
  • October 2007 (22)
  • September 2007 (25)
  • August 2007 (71)
  • July 2007 (22)
  • June 2007 (30)
  • May 2007 (49)
  • April 2007 (34)
  • March 2007 (33)
  • February 2007 (28)
  • January 2007 (21)
  • December 2006 (32)
  • November 2006 (35)
  • October 2006 (31)
  • September 2006 (37)
  • August 2006 (29)
  • July 2006 (15)
  • June 2006 (36)
  • May 2006 (15)
  • April 2006 (12)
  • March 2006 (28)
  • February 2006 (22)
  • January 2006 (40)
  • December 2005 (24)
  • November 2005 (22)
  • October 2005 (17)
  • September 2005 (10)
  • August 2005 (15)
  • July 2005 (16)
  • June 2005 (30)
  • May 2005 (26)
  • April 2005 (30)
  • March 2005 (43)
  • February 2005 (35)
  • January 2005 (19)
  • December 2004 (20)
  • November 2004 (27)
  • October 2004 (31)
  • September 2004 (18)
  • August 2004 (28)
  • July 2004 (32)
  • June 2004 (19)
  • May 2004 (16)
  • April 2004 (14)
  • March 2004 (28)
  • February 2004 (20)
  • January 2004 (17)
  • December 2003 (7)
  • November 2003 (11)
  • October 2003 (14)
  • September 2003 (13)
  • August 2003 (9)
  • July 2003 (12)

I sat in on a workshop on WF yesterday that David was running.

One of the interesting discussions that came up was around the "CallExternalMethod"/"HandleExternalEvent" Activities.

The idea of these Activities is that you can build a Workflow which makes a call out to the "outside world" using the "CallExternalMethod" Activity;

 

spacer

 

You can also have a Workflow wait for something to happen in the "outside world" by using the "HandleExternalEvent" Activity;

 

spacer

 

At build time with these Activities the only thing that the Workflow needs knowledge of is the definition of a .NET interface that provides methods that it (the Workflow Instance) can call and events that it (the Workflow Instance) can handle to receive data.

This means that the Workflow definition is very much abstracted from the means by which it sends information "out" and the means by which it receives notifications "in".

I made a few videos on this stuff which you can find up at wf.netfx3.com under the screencasts section. Specifically,

MSDN UK WF Nuggets - 10 - Communications from the Workflow to the Host

MSDN UK WF Nuggets - 11 - Communications from the Host to the Workflow

MSDN UK WF Nuggets - 12 - Bidirectional Communication (Host Workflow)

However. If you were, for instance, trying to build a Workflow that waited for something and that something happens to be a call into an ASMX web service then there's already an Activity that does this;

 

spacer

 

And there's also an Activity that will call a web service for you.

So, clearly, there's an idea here that sometimes you would use the general communication mechanism to talk between the Workflow Instance and "the outside world" but there are other times when a specific Activity is preferable as in the ASMX web services case.

In David's workshop, the question that we probably spent the most time on was "How do I decide when I use this Host/Workflow generic mechanism and when to use or build a specific Activity to achieve what I want".

It's an interesting question :-) Firstly, I think when it comes right down to it whichever path you take, the same core mechanism will underpin it (using queues that communicate with a Workflow instance) but you're still left with a choice of whether to go with a very generic mechanism or whether to build a specific Activity.

Imagine you need to do something like;

  1. Read an MSMQ message within a Workflow.
  2. Read a file within a Workflow.
  3. Read a WCF message within a Workflow.
  4. Gather a Yes/No response from a user within a Workflow.
  5. Talk to a database from within a Workflow

In each case, what do you do? Do you build a specific Activity that does what you want or do you use the general purpose "CallExternalMethod" Activity?

Here's what I think are some of the trade-offs between the two. I'm sure there's a lot more.

Build a Specific Activity

  1. Your activity is easily re-usable across different Workflows. An MSMQActivity is a useful thing to have.
  2. Your activity is easier for the Workflow builder to use. It has a clear purpose and inputs/outputs that line up with that purpose.
  3. If you need to be event-driven then you need to build a service to plug in to the runtime that will deliver the right events to your Activity. This means some code to support your Activity. Most of the code you write then goes into writing your Activity and its service.

Use the General "CallExternalMethod" Mechanism

  1. You can re-host the Workflow in different hosting environments and implement its communication in different ways each time. That is, you're not tied to a specific implementation of "communication".
  2. You can make dynamic choices in the host as to how the communication is implemented (i.e. have some fancy switch statement that chooses depending on the day of the week :-))
  3. You do not need to write a service to plug in to the runtime - the ExternalDataService bits already do that for you. Most of the code you write goes into the host.

So it seems that we have the Activity-centric way of doing things and the Host-centric way of doing things and I don't think it's simple enough that there's a "right" answer and each time you make this decision you'll have to evaluate against the pros/cons of each approach and decide what to do.

I thought I'd try and illustrate this with a simple scenario. Say I want to build a Windows Forms application and I want to have a Workflow that traps key presses and draws shapes on the screen.

Implementing that with "CallExternalMethod" looks something like this;

spacer

and it was pretty easy to implement once the definition of the interface that sits between the Workflow and the Host was established as;

 

  public enum Shape
  {
    Circle,
    Square,
    Triangle
  }
  [Serializable]
  public class KeyPressEventArgs : ExternalDataEventArgs
  {
    public KeyPressEventArgs(Guid g) : base(g)
    {
      this.WaitForIdle = true;
    }
    public KeyPressEventArgs(Guid g, char k) : base(g)
    {
      this.key = k;
      this.WaitForIdle = true;
    }    
    public char Key
    {
      get { return key; }
      set { key = value; }
    }
    private char key;
  }
  [ExternalDataExchange]
  public interface IUICommunication
  {
    void DrawShape(Shape s);
    event EventHandler<KeyPressEventArgs> KeyPress;    
  }

Here's the project file that does it - when the app's running you can press 's', 'c' or 't' and you'll get squares, circles and triangles on the screen. Note that I don't bother to keep a list of what's on the screen so if you invalidate the window your shapes will disappear.

What about doing this the alternative way with custom Activities? It's not too hard to build a DrawShapeActivity although there is the question of how it gets hold of a Graphics object to draw with. In terms of building a WaitForKeyPressActivity it's a bit trickier because it needs to be asynchronous because it could run for an indefinite period of time.

So, the WaitForKeyPressActivity needs a runtime service to support it and it's probably best if the DrawShapeActivity also uses some kind of service to get hold of a Graphics object to draw with.

Here's the project file that works this way - it should run the same way as the other one and I didn't spend too long on it but I'd say it was slightly harder than the other way of working. The Workflow ends up looking very similar;

 

spacer

 

but those two white boxes are custom Activities now rather than something that ships in the box. I also have a UIService class which helps those 2 Activities do what they need to do (i.e. draw to screen and draw shapes).

Going back to the list of 5 examples earlier - here's my thoughts on what I'd probably do unless I needed to be able to specifically achieve the following without needing to re-host the Workflow with different mechanisns;

  1. Read an MSMQ message within a Workflow (Activity!)
  2. Read a file within a Workflow (Activity!)
  3. Read a WCF message within a Workflow (Activity!)
  4. Gather a Yes/No response from a user within a Workflow (Host/Workflow comms)
  5. Talk to a database from within a Workflow (Activity!)

but, as I say, to me it's not a question of right or wrong.


Posted Thu, Nov 23 2006 5:51 AM by mtaulty

Comments

spacer
Sam Gentile wrote New and Notable 127
on Thu, Nov 23 2006 7:12 AM
I thought Thanksgiving morning is for adults to be sleeping in. Instead, not only are the kids up at
spacer
Javier Romero : Links para esta semana. wrote Javier Romero : Links para esta semana.
on Thu, Nov 30 2006 10:01 PM
PingBack from javier-romero.com/archives/2006/12/01/links-para-esta-semana/
spacer
Javier Romero wrote Links para esta semana.
on Thu, Feb 22 2007 8:43 AM
Creating CSS Friendly Websites with ASP.NET 2.0 [Via: ] Lollygag: Latest non-Atlas .NET Framework [Via:
spacer
Javier-Romero wrote Links para esta semana. (Dec 01 - 2006)
on Tue, Nov 13 2007 5:13 PM
Links para esta semana. (Dec 01 - 2006)
(C) Mike Taulty, 2009. All rights reserved. The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.
spacer
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.