Note that there are some explanatory texts on larger screens.

plurals
  1. POException escapes from workflow despite TryCatch activity
    primarykey
    data
    text
    <p>I have a workflow inside a Windows Service that is a loop that performs work periodically. The work is done inside a <a href="http://msdn.microsoft.com/en-us/library/system.activities.statements.trycatch.aspx" rel="nofollow noreferrer"><code>TryCatch</code></a> activity. The <a href="http://msdn.microsoft.com/en-us/library/system.activities.statements.trycatch.try.aspx" rel="nofollow noreferrer"><code>Try</code></a> property is a <a href="http://msdn.microsoft.com/en-us/library/system.activities.statements.transactionscope.aspx" rel="nofollow noreferrer"><code>TransactionScope</code></a> activity that wraps some custom activities that read and update a database. When the transaction fails, I would expect any exception that caused this to be caught by the <code>TryCatch</code>. However, my workflow aborts. The workflow I have is the following:</p> <pre><code>var wf = new While(true) { Body = new Sequence { Activities = { new TryCatch { Try = new TransactionScope { IsolationLevel = IsolationLevel.ReadCommitted, Body = new Sequence { Activities = { ..custom database activities.. } }, AbortInstanceOnTransactionFailure = false }, Catches = { new Catch&lt;Exception&gt; { Action = new ActivityAction&lt;Exception&gt; { Argument = exception, Handler = ..log error.. } } } }, new Delay { Duration = new InArgument&lt;TimeSpan&gt;(duration) } } }, } </code></pre> <p>In my case, it's possible that the database is sometimes unavailable so obviously the transaction won't commit. What happens in this case is that the workflow aborts with the following exception:</p> <blockquote> <p>System.OperationCanceledException: An error processing the current work item has caused the workflow to abort.</p> </blockquote> <p>The inner exception is:</p> <blockquote> <p>System.Transactions.TransactionException: The operation is not valid for the state of the transaction.</p> </blockquote> <p>This makes sense because I have just switched off the database. However, why isn't this exception handled by my <code>TryCatch</code> activity?</p> <p><strong>EDIT 1</strong>: Some additional information. I run the workflow using the <a href="http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.aspx" rel="nofollow noreferrer"><code>WorkflowApplication</code></a> class. To better see what's going on, I specified the properties <a href="http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.aborted.aspx" rel="nofollow noreferrer"><code>Aborted</code></a> and <a href="http://msdn.microsoft.com/en-us/library/system.activities.workflowapplication.onunhandledexception.aspx" rel="nofollow noreferrer"><code>OnUnhandledException</code></a>. When the exception occurs, it goes directly to <code>Aborted</code> and <code>OnUnhandledException</code> is skipped (although this is clearly an unhandled exception).</p> <p><strong>EDIT 2</strong>: I enabled the debug log and this provides some additional insight. The 'custom database activities' successfully run to completion. The first event log entry that indicates that something is wrong is a Verbose level message: <em>The runtime transaction has completed with the state 'Aborted'</em>. Next I see an Information message: <em>WorkflowInstance Id: 'dbd1ba5c-2d8a-428c-970d-21215d7e06d9' E2E Activity</em> (not sure what this means). And the Information message after that is: <em>Activity 'System.Activities.Statements.TransactionScope', DisplayName: 'Transaction for run immediately checks', InstanceId: '389' has completed in the 'Faulted' state</em>.</p> <p>After this message, I see that each parent (including the <code>TryCatch</code> activity) completes in the 'Faulted' state, ending with the abortion of my workflow.</p> <p><strong>EDIT 3</strong>: To be clear, everything works as expected when an exception occurs in any of the 'custom database activities'. The exception is caught and the workflow continues. It only goes wrong when the transaction can't commit at the end of the <code>TransactionScope</code>. See the following stacktrace that is logged from the <code>Aborted</code> callback:</p> <pre><code>at System.Transactions.TransactionStateInDoubt.Rollback(InternalTransaction tx, Exception e) at System.Transactions.Transaction.Rollback(Exception e) at System.Activities.Runtime.ActivityExecutor.CompleteTransactionWorkItem.HandleException(Exception exception) </code></pre> <p>If you follow the calls from <code>TransactionScope.OnCompletion(...)</code>, eventually you will arrive at the <code>ActivityExecutor</code> class from the stacktrace.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload