After further investigating this issue, I want to summarize the differences:
Terminate :
- the Completed event of the workflow application will be triggered
- the CompletionState (WorkflowApplicationCompletedEventArgs) is Faulted
- the Unloaded event of the workflow application will be triggered
- the workflow completes
- OnBodyCompleted on the activity will be called
Cancel:
- the Completed event of the workflow application will be triggered
- the CompletionState (WorkflowApplicationCompletedEventArgs) is Cancelled
- the Unloaded event of the workflow application will be triggered
- the workflow completes
- OnBodyCompleted on the activity will be called
Abort:
- the Aborted event of the workflow application will be triggered
- the workflow does not complete
An unhandled exception
- triggers OnUnhandledException
- in this eventhandler the return value (of type UnhandledExceptionAction) determines what will happen next:
- UnhandledExceptionAction.Terminate will terminate the workflow instance
- UnhandledExceptionAction.Cancel will cancel the workflow instance
- UnhandledExceptionAction.Abort will abort the workflow instance
- Each will trigger the corresponding events explained above
Update: Abort does not seem to trigger unloading of the instance in the SQL persistence store. So it seems to me, you better use Cancel or Terminate and if you have to perform some action based upon the completion status, you can check CompletionState in the Complete event.