You may implement a state machine workflow and deploy it to a production server. Intermittently you may find that the workflow does not work as expected. If you enable workflow logging following the instructions in KB972914, you will see System.Workflow.Activities.EventDeliveryFailedException in the trace log:

 

Event "YourEventName" on interface type "YourInternfaceType" for instance id "xxxxxxxx -xxxx-xxxx-xxxx-xxxxxxxxxxxx" cannot be delivered.

 

 

The inner exception message may be as follows:

 

Queue 'Message Properties

Interface Type: YourInterfaceType

Method Name:YourEventMethod

CorrelationValues:

' is not enabled.

 

 

The message "Queue '{0}' is not enabled." happens when the current state of the state machine does not know how to handle a specific event. Therefore EventDeliveryFailedException will be thrown.  

 

How does this happen? Some customers have implemented their own task list table so that the users can learn which tasks are waiting by querying the task list table. After the user finishes the task, he may update the task list table and send the event to the workflow instance so that the workflow instance will move to the next state. If the state where the workflow instance stays is inconsistent with the state recorded in task list table, the above exception will be thrown. For example, the workflow instance is waiting for Event1 in State1. However the user thinks he accomplished the task in State2 according to the task list table and then sends the Event2 which should be handled by State2. Therefore EventDeliveryFailedException will be thrown.

 

Why does the inconsistence between the task list table and the workflow instance occur? A common cause is related to the transaction use in WF3/3.5 applications. Some customers used the following code snippet after they accomplished the task:

 

using (TransactionScope ts = new TransactionScope())
{

Updating the task list table

Call MyWorkflowService to send event to workflow instance

}

 

Where MyWorkflowService is a custom class which implements several interfaces and
acts as ExternalDataExchangeService .

 

The customers thought the TransactionScope should cover both of “Updating the task list table” and workflow instance. However the WF runtime itself uses a TransactionScope to suppress any external transactions. Therefore the “Updating the task list table” and workflow instance are in different transactions. Sometimes the users may successfully update the task list table to State2 but workflow instance may fail to move from State1 to State2. Then this inconsistence occurs.

 

Resolution:

 

In a workflow application you usually need to handle 2 categories of data.

 

1.       Application business data, e.g. the submitted documents.

2.       The internal state of the WF runtime, e.g. the data saved by persistence service.

 

If they want to join the same transaction, we can:

 

1.       All business data operations can be processed in workflow by using TransactionScopeActivity .

2.       The business data operations can be processed in the local ExternalDataExchange service (not in workflow). But we need to implement IPendingWork interface to let the local service participate in the workflow runtime batching mechanism. 

You can find a sample Using WorkflowCommitWorkBatch Service Sample . (It is the transaction service sample in WF SDK samples)

 

There is an old post which discusses the WF transaction. It is still there:
http://social.msdn.microsoft.com/forums/en-US/windowsworkflowfoundation/thread/9dbf332d-4d27-49c4-92dc-1f3bd8959873/

 

Regards, 

 

XinJin from APAC DSI Team