Hi Naresh,
You can nest both the child state activities into a parent state activity which will have the event driven that invokes another workflow. i.e.
State Machine Workflow
State 1 (Parent State)
|__ EventDriven1 that Invokes Sequential Workflow
|__ State 2 (with event driven activity)
|__ State 3 (with event driven activity)
This way the common functionality for invoking the sequential workflow can be bubbled up to the parent and need not be duplicated
Hope this helps.
- Vihang
System.Workflow.Activities.EventDeliveryFailedException:
Event "CommodityQuoteRequestedEvent" on interface type "HighEnergy.WorkflowUtils.IWorkflowDataExchangeService"
for instance id "ac642cd7-7842-4fae-a7da-2d1171a35785" cannot be delivered. >
System.InvalidOperationException: Queue 'Message Properties
Interface Type:HighEnergy.WorkflowUtils.IWorkflowDataExchangeService
Method Name:CommodityQuoteRequestedEvent
CorrelationValues:
' is not enabled.
at System.Workflow.Runtime.WorkflowQueuingService.EnqueueEvent(IComparable queueName, Object item)
at System.Workflow.Runtime.WorkflowExecutor.EnqueueItem(IComparable queueName, Object item, IPendingWork pendingWork, Object workItem)
at System.Workflow.Runtime.WorkflowInstance.EnqueueItem(IComparable queueName, Object item, IPendingWork pendingWork, Object workItem)
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
End of inner exception stack trace
at System.Workflow.Activities.WorkflowMessageEventHandler.EventHandler(Object sender, ExternalDataEventArgs eventArgs)
at HighEnergy.WorkflowUtils.WorkflowDataExchangeService.FireCommodityQuoteRequestedEvent(CommodityQuoteRequestedEventArgs eventArgs) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyWorkflowUtils\WorkflowDataExchangeService.cs:line 28
at HighEnergy.Services.TradeService.CreateTrade(TradeVO tradeVO, Int64 contactId) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyServices\TradeService.cs:line 78
at HighEnergy.Services.TradeService.SaveTrade(TradeVO tradeVO, Int64 contactId) in C:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyServices\TradeService.cs:line 47
at TradeService.SaveTrade(TradeVO tradeVO, Int64 contactId) in c:\HighEnergy\high_energy\Development\Code\Microsoft\HighEnergy\HighEnergyWebServices\App_Code\TradeService.cs:line 49
End of inner exception stack trace
Here's the structure of my workflow:
??<StateMachineWorkflowActivity x:Class="HighEnergy.Services.ProcessCommodityQuoteWorkflow"
InitialStateName="ProcessCommodityQuoteWorkflowInitialState"
x:Name="ProcessCommodityQuoteWorkflow"
DynamicUpdateCondition="{x:Null}"
CompletedStateName="ProcessEnd" ...>
<StateActivity x:Name="ProcessingQuoteRequest">
<StateActivity x:Name="ProcessCommodityQuoteWorkflowInitialState" />
<StateActivity x:Name="WaitingForPrice">
<EventDrivenActivity x:Name="ProcessTradePricedEvent">
...
</EventDrivenActivity>
</StateActivity>
<StateActivity x:Name="WaitingForSalesApproval">
<EventDrivenActivity x:Name="ProcessSalesApprovedEvent">
...
</EventDrivenActivity>
</StateActivity>
<EventDrivenActivity x:Name="ProcessCommodityQuoteRequestedEvent">
<HandleExternalEventActivity
Invoked="ValidateAndSaveTrade_Invoked"
x:Name="ValidateAndSaveTrade"
EventName="CommodityQuoteRequestedEvent"
InterfaceType="{x:Type HighEnergy.WorkflowUtils.IWorkflowDataExchangeService}" />
...
</EventDrivenActivity>
</StateActivity>
<StateActivity x:Name="ProcessEnd" />
</StateMachineWorkflowActivity>
Note that the initial state (ProcessCommodityQuoteWorkflowInitialState) is now empty. Its event driven activity is moved up to its parent state.
Naresh,
This is because when raising an event on the initial state, the sink must be contained inside the initial state. You'll need to move or copy the event driven back to the initial state.
Arjun
What about factoring out a state C that is a SetState target of the common event activity of A and B that contains the workflow and whose eventdriven event is a delay of 0? Where does A and B go after the event? State C could determine where to return to based on something else in the workflow.
This is a great example of why WF needs a synchronous 'Call Workflow' activity -- workflow refactoring.
Very creative! I think this would work. Whether in state A or B, the response to the event is the same including what the next state is. So the next state for state C will remain the same.
I think your suggestion for calling workflows synchronously makes sense. Either that or the state machine implementation should be changed to allow nested states without any activities and have them pick up activities from the parent state.
This is exactly what I need as well. I just posted a new thread today on the need to have Hierarchical State Machine support exactly as outlined in the book "Practical Statecharts in C/C++" by Miro Samek. This would get what you want. The parent event handlers and behavior should be inherited by the child states. WF doesn't seem to work that way. You leave child state when receiving a parent state event. This should not happen.