none
Finally never executed

    Question

  • If you use this XAML

    <Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication2.Workflow1" sap:VirtualizedContainerService.HintSize="458,297" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:s4="clr-namespace:System;assembly=System.ServiceModel" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <TryCatch sad:XamlDebuggerXmlReader.FileName="C:\Development\WorkflowConsoleApplication2\WorkflowConsoleApplication2\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="418,257">
      <TryCatch.Finally>
       <WriteLine sap:VirtualizedContainerService.HintSize="400,100" Text="Finally called" />
      </TryCatch.Finally>
      <TryCatch.Try>
       <Throw Exception="[New System.Exception(&quot;BÄNG&quot;)]" sap:VirtualizedContainerService.HintSize="400,100" />
      </TryCatch.Try>
     </TryCatch>
    </Activity>

    and this code

    try
    {
       WorkflowInvoker.Invoke(new Workflow1());
    }
    catch { }

     

    you see that the finally is never executed. This is not quite what I expect from a "finally" or am I missing something?

    Thursday, May 06, 2010 6:23 PM

Answers

  • Hi Tobias,

    I have done some research into this. I will get our documentation updated to describe the fact that the Finally portion of the TryCatch activity does not match exactly the C# semantics of try/catch/finally, and also describe the cases in which the behavior does match.

    If an unhandled exception escapes past the root of the workflow, there are 3 things that can occur: The workflow Aborts, it is Terminated, or it is Cancelled.

    When a workflow aborts, it immediately stops executing, and is removed from memory. However, if the workflow has been previously persisted, that previous state remains in the persistence store and the workflow can be reloaded from that previous point. The Finally block (or compensation or cancellation) will not run in this case. This is similar to calling FailFast in C# code:

    try
    {
     Environment.FailFast("Game Over.");
    }
    finally
    {
     Console.WriteLine("Not Called");
    }
    

    When a workflow terminates due to an unhandled exception escaping the root, it is very similar to abort except that if the workflow is persisted, it will be removed from persistence as part of the termination process. Finally, Cancellation, and Compensation will not run in this case either. Terminate is the default behavior for WorkflowApplication.

    When a workflow is cancelled due to an unhandled exception escaping the root, Compensation, Cancellation, and the Finally handler will get scheduled. Here is an example:

     TryCatch tc = new TryCatch
     {
      Try = new Throw { Exception = new InArgument<Exception>(env => new Exception("Throw")) },
      Finally = new WriteLine { Text = "Finally!" }
     };
     ManualResetEvent mre = new ManualResetEvent(false);
     WorkflowApplication app = new WorkflowApplication(tc);
     app.OnUnhandledException = a => UnhandledExceptionAction.Cancel;
     app.Completed = a => mre.Set();
     app.Run();
     mre.WaitOne();
    

    If you specify Cancel as the behavior for unhandled exceptions escaping the root of the workflow then it should give the desired behavior. I have passed this feedback along and will ensure that the documentation is updated to reflect this.

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

     

     

    Monday, May 10, 2010 3:17 PM
    Moderator

All replies

  • Finally executed if you have least one catch

    <Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication1.Workflow1" sap:VirtualizedContainerService.HintSize="458,305" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:s4="clr-namespace:System;assembly=System.ServiceModel" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <TryCatch sad:XamlDebuggerXmlReader.FileName="c:\users\oleg\documents\visual studio 2010\Projects\Labs\WorkflowConsoleApplication1\WorkflowConsoleApplication1\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="418,287">
     <TryCatch.Try>
      <Throw Exception="[New System.Exception(&quot;BÄNG&quot;)]" sap:VirtualizedContainerService.HintSize="400,100" />
     </TryCatch.Try>
     <TryCatch.Catches>
      <Catch x:TypeArguments="s:Exception" sap:VirtualizedContainerService.HintSize="404,21">
      <sap:WorkflowViewStateService.ViewState>
       <scg3:Dictionary x:TypeArguments="x:String, x:Object">
       <x:Boolean x:Key="IsExpanded">False</x:Boolean>
       <x:Boolean x:Key="IsPinned">False</x:Boolean>
       </scg3:Dictionary>
      </sap:WorkflowViewStateService.ViewState>
      <ActivityAction x:TypeArguments="s:Exception">
       <ActivityAction.Argument>
       <DelegateInArgument x:TypeArguments="s:Exception" Name="exception" />
       </ActivityAction.Argument>
       <WriteLine sap:VirtualizedContainerService.HintSize="394,75" Text="Exception handled" />
      </ActivityAction>
      </Catch>
     </TryCatch.Catches>
     <TryCatch.Finally>
      <WriteLine sap:VirtualizedContainerService.HintSize="400,100" Text="Finally called" />
     </TryCatch.Finally>
     </TryCatch>
    </Activity>

    why, i don't know

     

    TryCatch Activity Designer
    Thursday, May 06, 2010 6:41 PM
  • Yes I can confirm the finally gets executed if the "Try/Catch" contains at least one Exception in "Catches". But still this is not quite what I expect.

    For me it looks like this is a serious bug...

    http://my-tech-talk.blogspot.com/2010/05/workflow-4-bugfest-exception-handling.html
    Friday, May 07, 2010 7:36 AM
  • Hi Tobias,

    I have done some research into this. I will get our documentation updated to describe the fact that the Finally portion of the TryCatch activity does not match exactly the C# semantics of try/catch/finally, and also describe the cases in which the behavior does match.

    If an unhandled exception escapes past the root of the workflow, there are 3 things that can occur: The workflow Aborts, it is Terminated, or it is Cancelled.

    When a workflow aborts, it immediately stops executing, and is removed from memory. However, if the workflow has been previously persisted, that previous state remains in the persistence store and the workflow can be reloaded from that previous point. The Finally block (or compensation or cancellation) will not run in this case. This is similar to calling FailFast in C# code:

    try
    {
     Environment.FailFast("Game Over.");
    }
    finally
    {
     Console.WriteLine("Not Called");
    }
    

    When a workflow terminates due to an unhandled exception escaping the root, it is very similar to abort except that if the workflow is persisted, it will be removed from persistence as part of the termination process. Finally, Cancellation, and Compensation will not run in this case either. Terminate is the default behavior for WorkflowApplication.

    When a workflow is cancelled due to an unhandled exception escaping the root, Compensation, Cancellation, and the Finally handler will get scheduled. Here is an example:

     TryCatch tc = new TryCatch
     {
      Try = new Throw { Exception = new InArgument<Exception>(env => new Exception("Throw")) },
      Finally = new WriteLine { Text = "Finally!" }
     };
     ManualResetEvent mre = new ManualResetEvent(false);
     WorkflowApplication app = new WorkflowApplication(tc);
     app.OnUnhandledException = a => UnhandledExceptionAction.Cancel;
     app.Completed = a => mre.Set();
     app.Run();
     mre.WaitOne();
    

    If you specify Cancel as the behavior for unhandled exceptions escaping the root of the workflow then it should give the desired behavior. I have passed this feedback along and will ensure that the documentation is updated to reflect this.

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

     

     

    Monday, May 10, 2010 3:17 PM
    Moderator
  •  

    Setting Workflowapplication.OnUnhandledException to a => UnhandledExceptionAction.Cancel

    modifies the behavior both for the Try/Catch and the Compensable.Activity to what I would expect.

     

    Thanks!

    Tobias

    Tuesday, May 11, 2010 7:30 AM
  • You're welcome!

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    Tuesday, May 11, 2010 2:16 PM
    Moderator