Persistence in learning WF (15): State Machine Workflow

Source: Internet
Author: User

 

[Stick to the top] Stick to learning WF Article Indexes

This article mainly introduces the basic knowledge of the state machine workflow in WF. The state machine workflow and sequential workflow are different. Ordered workflows are generally relatively fixed and predictable, and there are many interactions with the system. State Machine workflows are generally unpredictable, and there will be more interactions with people. Generally, it is better to use state machine workflows when there is a rollback process, it is very important to select a sequence workflow or a state machine workflow correctly.

Statemachineworkflowactivity is the base class of a state machine workflow. stateactivity can accept multiple eventdrivenactivities, one stateinitializationactivity, and one statefinalizationactivity. It can also contain setstateactivity and stateactivity relationships such:

Your state machine workflow must contain many States. Which one should you start with? statemacnineworkflowactivity has an initialstatename attribute, which can be used to set the Initial State points. There is also a completedstatename attribute, which indicates that the state machine workflow is completed. If this attribute is set, this State cannot contain any sub-activities. This attribute is optional because it is not mandatory. Except the two states, all the other states are process state nodes. Generally, each node uses setstate to set the next state. If no State is set, the process is suspended when all eventdrivenactivity is executed.


I. Example of implementing a state machine Workflow

1. We have already opened a car as an example to illustrate that when we drive a car, there will be many states, such as not starting, running, reversing, and so on. These statuses cannot be converted at will. In the following example, we first define the local service interface,CodeAs follows (icarservice. CS ):

[Externaldataexchange]Public InterfaceIcarservices {EventEventhandler <externaldataeventargs> startengine;EventEventhandler <externaldataeventargs> stopengine;EventEventhandler <externaldataeventargs> stopmovement;EventEventhandler <externaldataeventargs> goforward;EventEventhandler <externaldataeventargs> goreverse;EventEventhandler <externaldataeventargs> leavecar;
EventEventhandler <externaldataeventargs> beephorn;
 
VoidOnsendmessage (string message );}
This interface defines events related to car operations. The onsendmessage method will give the hostProgramReturn a message.
 

2. We define the carservice class to implement this service. The Code is as follows (carservice. CS ):
 Namespace Carystateworkflowlibrary { Public   Class Carservice: icarservices { Public   Event Eventhandler <externaldataeventargs> startengine; Public   Event Eventhandler <externaldataeventargs> stopengine; Public   Event Eventhandler <externaldataeventargs> stopmovement; Public   Event Eventhandler <externaldataeventargs> goforward; Public   Event Eventhandler <externaldataeventargs> goreverse; Public   Event Eventhandler <externaldataeventargs> beephorn; Public   Event Eventhandler <externaldataeventargs> leavecar;
Public Void Onsendmessage (string message ){ If (Messagereceived! = Null ) {Messagereceivedeventargs ARGs = New Messagereceivedeventargs (workflowenvironment. workflowinstanceid, message); messagereceived ( This , ArgS );}} Public Event Eventhandler <messagereceivedeventargs> messagereceived; Public Void Onstartengine (externaldataeventargs ARGs ){If (Startengine! = Null ) {Startengine ( Null , ArgS );}} Public Void Onstopengine (externaldataeventargs ARGs ){ If (Stopengine! = Null ) {Stopengine ( Null , ArgS );}} Public Void Onstopmovement (externaldataeventargs ARGs ){If (Stopmovement! = Null ) {Stopmovement ( Null , ArgS );}} Public Void Ongoforward (externaldataeventargs ARGs ){ If (Goforward! = Null ) {Goforward ( Null , ArgS );}} Public Void Ongoreverse (externaldataeventargs ARGs ){If (Goreverse! = Null ) {Goreverse ( Null , ArgS );}} Public Void Onbeephorn (externaldataeventargs ARGs ){ If (Beephorn! = Null ) {Beephorn ( Null , ArgS );}} Public Void Onleavecar (externaldataeventargs ARGs ){If (Leavecar! = Null ) {Leavecar ( Null , ArgS );}}}}
 
The onsendmessage method uses the messagereceived event to send the message to the Host Program. messagereceived has an event parameter.
Messagereceivedeventargs. The code for this class is as follows (messagereceivedeventargs. CS ):
[Serializable]Public ClassMessagereceivedeventargs: externaldataeventargs {PrivateString message;PublicMessagereceivedeventargs (guid instanceid, string message ):Base(Instanceid ){This. Message = message ;}PublicString message {Get{ReturnMessage ;}Set{Message =Value;}}}
 

3. Implement a workflow, such:
 

 
The workflow has five States. As shown in, notrunningstate indicates the initial state of the state machine workflow, and donewithcarstate indicates the end state.
Status, and others are process nodes. Images in the upper left corner of each status can identify the status category.
Then we can set events in each status, such:
 
 
 
Taking eventstartengine in notrunningstate as an example, this eventdriven activity contains three sub-activities, one
Handlestartengine is used to receive events, operate on cars, and then a callexternalmethod activity to return relevant information
The Host Program is finally a setstate activity to set the next state. Other statuses are similar.
 
I wonder if you have noticed that there is an eventbeephorn activity in the state machine workflow and it is not in any State. This is because of the whistle of the car.
Action is not a state, and it can be done in any state, so we put it out, it contains a handlebeephorn and
Callexternalmethod activity.
 

4. Implement the host program. We use the winform program, for example:
 
 
 
In the host Program, we load the local service and call the response event in the response action. The specific code is in the final download.
 

Ii. Eliminate repeated event handling

In our previous workflow, the statuses movingforwardstate and movinginreversestate receive the same event,
All are stopmovement events. Let's refactor this part. We Add a new state named movingstate based on the above workflow.
And then drag the movingforwardstate and movinginreversestate to the movingstate as its sub-activity, and move the movingforwardstate
Or the eventstopmovement in the movinginreversestate state is dragged to the movingstate as a sub-activity, and the movingforwardstate and
You can delete a sub-activity in the movinginreversestate state. The final completion is as follows:
 

 
In this way, any sub-activity in the movingstate can respond to events in eventstopmovement. Here, note that
Setstate still points to the original activity, that is, the subactivity of the current movingstate, instead of the movingstate activity. Now run the program again and the original
The effect is the same.
 

3. Identify available events
 




1. The effect of this part is shown in the figure above. When we click startengine, The unexecutable action button will be gray. We use workflowinstance.
The getworkflowqueuedata method of is processed according to the return value of the method. The following code is added to the form constructor:
Btnstartengine. Tag ="Startengine"; Btnstopengine. Tag ="Stopengine"; Btnforward. Tag ="Goforward"; Btnreverse. Tag ="Goreverse"; Btnstop. Tag ="Stopmovement"; Btnbeephorn. Tag ="Beephorn"; Btnleavecar. Tag ="Leavecar";

2. when the state machine workflow is transitioned to a new state and waits for event processing, the workflow will change to the idle state. We will judge and set whether the response button is enabled in the idle event of the workflow. The Code is as follows:

 Private   Void Workflowruntime_workflowidled ( Object Sender, workfloweventargs e) {updatedelegate thedelegate = Delegate () {Enableeventbuttons (False );. Readonlycollection <workflowqueueinfo> queueinfodata = instancewrapper. workflowinstance. getworkflowqueuedata (); If (Queueinfodata! = Null ){ Foreach (Workflowqueueinfo info In Queueinfodata) {eventqueuename eventqueue = info. queuename As Eventqueuename; If (Eventqueue = Null ){ Break ;} Enablebuttonforevent (eventqueue. methodname );}}}; This . Invoke (thedelegate );}
 

Each workflowqueueinfo object contains a queuename attribute, which is an instance of the eventqueuename object and has
The methodname attribute identifies the name of the external event called in the current queue. In enablebuttonforevent, we determine the name based on the tag attribute and this attribute.
The Code is as follows:
Private VoidEnablebuttonforevent (string eventname ){// If the tag attribute of the control is the same as the event name, enableForeach(ControlIn This. Controls ){If(ControlIsButton & control. Tag! =Null){If(Control. Tag. tostring () = eventname) {control. Enabled =True;}}}}

In this way, you can.


Iv. Access runtime information

The statemachineworkflowinstance class provided by WF records information about the current instance. The following code obtains the current instance.

 
Statemachineworkflowinstance statemachine =NewStatemachineworkflowinstance
(Workflowmanager. workflowruntime, instancewrapper. workflowinstance. instanceid );
 
In this way, we can get some information about the current instance, such as currentstate, currentstatename, and statehistory.
The historical record of state change. You can set the next State using the setstate method. For details, refer to msdn.
 

Download the main code: carystatemachineworkflow

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.