1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
5 namespace System.Activities.Hosting
9 using System.Activities.DynamicUpdate;
10 using System.Activities.Runtime;
11 using System.Activities.Tracking;
12 using System.Activities.Validation;
13 using System.Collections.Generic;
14 using System.Collections.ObjectModel;
15 using System.Diagnostics;
16 using System.Diagnostics.CodeAnalysis;
17 using System.Globalization;
19 using System.Runtime.DurableInstancing;
20 using System.Threading;
21 using System.Xml.Linq;
23 [Fx.Tag.XamlVisible(false)]
24 public abstract class WorkflowInstance
26 static readonly IDictionary<string, LocationInfo> EmptyMappedVariablesDictionary = new ReadOnlyDictionaryInternal<string, LocationInfo>(new Dictionary<string, LocationInfo>(0));
31 WorkflowInstanceControl controller;
32 TrackingProvider trackingProvider;
33 SynchronizationContext syncContext;
34 LocationReferenceEnvironment hostEnvironment;
35 ActivityExecutor executor;
36 int isPerformingOperation;
38 WorkflowInstanceExtensionCollection extensions;
40 // Tracking for one-time actions per in-memory instance
41 bool hasTrackedResumed;
42 bool hasTrackedCompletion;
45 Exception abortedException;
48 StackTrace abortStack;
51 protected WorkflowInstance(Activity workflowDefinition)
52 : this(workflowDefinition, null)
56 protected WorkflowInstance(Activity workflowDefinition, WorkflowIdentity definitionIdentity)
58 if (workflowDefinition == null)
60 throw FxTrace.Exception.ArgumentNull("workflowDefinition");
63 this.WorkflowDefinition = workflowDefinition;
64 this.DefinitionIdentity = definitionIdentity;
67 public abstract Guid Id
72 internal bool HasTrackingParticipant
78 internal bool HasTrackedStarted
84 internal bool HasPersistenceModule
90 public SynchronizationContext SynchronizationContext
94 return this.syncContext;
99 this.syncContext = value;
103 public LocationReferenceEnvironment HostEnvironment
107 return this.hostEnvironment;
112 this.hostEnvironment = value;
116 public Activity WorkflowDefinition
122 public WorkflowIdentity DefinitionIdentity
128 protected bool IsReadOnly
132 return this.isInitialized;
136 protected internal abstract bool SupportsInstanceKeys
141 // this is going away
142 internal TrackingProvider TrackingProvider
146 Fx.Assert(HasTrackingParticipant, "we should only be called if we have a tracking participant");
147 return this.trackingProvider;
151 protected WorkflowInstanceControl Controller
155 if (!this.isInitialized)
157 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ControllerInvalidBeforeInitialize));
160 return this.controller;
164 // host-facing access to our cascading ExtensionManager resolution
165 protected internal T GetExtension<T>() where T : class
167 if (this.extensions != null)
169 return this.extensions.Find<T>();
177 protected internal IEnumerable<T> GetExtensions<T>() where T : class
179 if (this.extensions != null)
181 return this.extensions.FindAll<T>();
189 // locks down the given extensions manager and runs cache metadata on the workflow definition
190 protected void RegisterExtensionManager(WorkflowInstanceExtensionManager extensionManager)
192 ValidateWorkflow(extensionManager);
193 this.extensions = WorkflowInstanceExtensionManager.CreateInstanceExtensions(this.WorkflowDefinition, extensionManager);
194 if (this.extensions != null)
196 this.HasPersistenceModule = this.extensions.HasPersistenceModule;
200 // dispose the extensions that implement IDisposable
201 protected void DisposeExtensions()
203 if (this.extensions != null)
205 this.extensions.Dispose();
206 this.extensions = null;
210 protected static IList<ActivityBlockingUpdate> GetActivitiesBlockingUpdate(object deserializedRuntimeState, DynamicUpdateMap updateMap)
212 ActivityExecutor executor = deserializedRuntimeState as ActivityExecutor;
213 if (executor == null)
215 throw FxTrace.Exception.Argument("deserializedRuntimeState", SR.InvalidRuntimeState);
217 if (updateMap == null)
219 throw FxTrace.Exception.ArgumentNull("updateMap");
222 DynamicUpdateMap rootMap = updateMap;
223 if (updateMap.IsForImplementation)
225 rootMap = updateMap.AsRootMap();
227 IList<ActivityBlockingUpdate> result = executor.GetActivitiesBlockingUpdate(rootMap);
230 result = new List<ActivityBlockingUpdate>();
236 // used for Create scenarios where you are providing root information
237 protected void Initialize(IDictionary<string, object> workflowArgumentValues, IList<Handle> workflowExecutionProperties)
241 this.executor = new ActivityExecutor(this);
243 EnsureDefinitionReady();
244 // workflowArgumentValues signals whether we are a new or loaded instance, so we can't pass in null.
245 // workflowExecutionProperties is allowed to be null
246 InitializeCore(workflowArgumentValues ?? ActivityUtilities.EmptyParameters, workflowExecutionProperties);
249 // used for Load scenarios where you are rehydrating a WorkflowInstance
250 protected void Initialize(object deserializedRuntimeState)
252 Initialize(deserializedRuntimeState, null);
255 protected void Initialize(object deserializedRuntimeState, DynamicUpdateMap updateMap)
259 this.executor = deserializedRuntimeState as ActivityExecutor;
261 if (this.executor == null)
263 throw FxTrace.Exception.Argument("deserializedRuntimeState", SR.InvalidRuntimeState);
265 this.executor.ThrowIfNonSerializable();
267 EnsureDefinitionReady();
269 WorkflowIdentity originalDefinitionIdentity = this.executor.WorkflowIdentity;
270 bool success = false;
271 Collection<ActivityBlockingUpdate> updateErrors = null;
274 if (updateMap != null)
276 // check if map is for implementaiton,
277 if (updateMap.IsForImplementation)
279 // if so, the definition root must be an activity
280 // with no public/imported children and no public/imported delegates.
281 if (DynamicUpdateMap.CanUseImplementationMapAsRoot(this.WorkflowDefinition))
283 updateMap = updateMap.AsRootMap();
287 throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidImplementationAsWorkflowRoot));
291 updateMap.ThrowIfInvalid(this.WorkflowDefinition);
293 this.executor.WorkflowIdentity = this.DefinitionIdentity;
295 this.executor.UpdateInstancePhase1(updateMap, this.WorkflowDefinition, ref updateErrors);
296 ThrowIfDynamicUpdateErrorExists(updateErrors);
299 InitializeCore(null, null);
301 if (updateMap != null)
303 this.executor.UpdateInstancePhase2(updateMap, ref updateErrors);
304 ThrowIfDynamicUpdateErrorExists(updateErrors);
305 // Track that dynamic update is successful
306 if (this.Controller.TrackingEnabled)
308 this.Controller.Track(new WorkflowInstanceUpdatedRecord(this.Id, this.WorkflowDefinition.DisplayName, originalDefinitionIdentity, this.executor.WorkflowIdentity));
314 catch (InstanceUpdateException updateException)
316 // Can't track through the controller because initialization failed
317 if (this.HasTrackingParticipant && this.TrackingProvider.ShouldTrackWorkflowInstanceRecords)
319 IList<ActivityBlockingUpdate> blockingActivities = updateException.BlockingActivities;
320 if (blockingActivities.Count == 0)
322 blockingActivities = new List<ActivityBlockingUpdate>
324 new ActivityBlockingUpdate(this.WorkflowDefinition, this.WorkflowDefinition.Id, updateException.Message)
327 this.TrackingProvider.AddRecord(new WorkflowInstanceUpdatedRecord(this.Id, this.WorkflowDefinition.DisplayName, originalDefinitionIdentity, this.DefinitionIdentity, blockingActivities));
333 if (updateMap != null && !success)
335 executor.MakeNonSerializable();
340 void ThrowIfDynamicUpdateErrorExists(Collection<ActivityBlockingUpdate> updateErrors)
342 if (updateErrors != null && updateErrors.Count > 0)
344 // update error found
347 throw FxTrace.Exception.AsError(new InstanceUpdateException(updateErrors));
351 void ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager)
353 if (!WorkflowDefinition.IsRuntimeReady)
355 LocationReferenceEnvironment localEnvironment = this.hostEnvironment;
356 if (localEnvironment == null)
358 LocationReferenceEnvironment parentEnvironment = null;
359 if (extensionManager != null && extensionManager.SymbolResolver != null)
361 parentEnvironment = extensionManager.SymbolResolver.AsLocationReferenceEnvironment();
363 localEnvironment = new ActivityLocationReferenceEnvironment(parentEnvironment);
365 IList<ValidationError> validationErrors = null;
366 ActivityUtilities.CacheRootMetadata(WorkflowDefinition, localEnvironment, ProcessActivityTreeOptions.FullCachingOptions, null, ref validationErrors);
367 ActivityValidationServices.ThrowIfViolationsExist(validationErrors);
371 void EnsureDefinitionReady()
373 if (this.extensions != null)
375 this.extensions.Initialize();
376 if (this.extensions.HasTrackingParticipant)
378 this.HasTrackingParticipant = true;
379 if (this.trackingProvider == null)
381 this.trackingProvider = new TrackingProvider(this.WorkflowDefinition);
385 // TrackingProvider could be non-null if an earlier initialization attempt failed.
386 // This happens when WorkflowApplication calls Abort after a load failure. In this
387 // case we want to preserve any pending tracking records (e.g. DU failure).
388 this.trackingProvider.ClearParticipants();
390 foreach (TrackingParticipant trackingParticipant in GetExtensions<TrackingParticipant>())
392 this.trackingProvider.AddParticipant(trackingParticipant);
398 // need to ensure the workflow has been validated since the host isn't using extensions (and so didn't register anything)
399 ValidateWorkflow(null);
403 void InitializeCore(IDictionary<string, object> workflowArgumentValues, IList<Handle> workflowExecutionProperties)
405 Fx.Assert(this.WorkflowDefinition.IsRuntimeReady, "EnsureDefinitionReady should have been called");
406 Fx.Assert(this.executor != null, "at this point, we better have an executor");
408 // Do Argument validation for root activities
409 WorkflowDefinition.HasBeenAssociatedWithAnInstance = true;
411 if (workflowArgumentValues != null)
413 IDictionary<string, object> actualInputs = workflowArgumentValues;
415 if (object.ReferenceEquals(actualInputs, ActivityUtilities.EmptyParameters))
420 if (this.WorkflowDefinition.RuntimeArguments.Count > 0 || (actualInputs != null && actualInputs.Count > 0))
422 ActivityValidationServices.ValidateRootInputs(this.WorkflowDefinition, actualInputs);
425 this.executor.ScheduleRootActivity(this.WorkflowDefinition, actualInputs, workflowExecutionProperties);
429 this.executor.OnDeserialized(this.WorkflowDefinition, this);
432 this.executor.Open(this.SynchronizationContext);
433 this.controller = new WorkflowInstanceControl(this, this.executor);
434 this.isInitialized = true;
436 if (this.extensions != null && this.extensions.HasWorkflowInstanceExtensions)
438 WorkflowInstanceProxy proxy = new WorkflowInstanceProxy(this);
440 for (int i = 0; i < this.extensions.WorkflowInstanceExtensions.Count; i++)
442 IWorkflowInstanceExtension extension = this.extensions.WorkflowInstanceExtensions[i];
443 extension.SetInstance(proxy);
448 protected void ThrowIfReadOnly()
450 if (this.isInitialized)
452 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowInstanceIsReadOnly(this.Id)));
456 protected internal abstract IAsyncResult OnBeginResumeBookmark(Bookmark bookmark, object value, TimeSpan timeout, AsyncCallback callback, object state);
457 protected internal abstract BookmarkResumptionResult OnEndResumeBookmark(IAsyncResult result);
459 protected internal abstract IAsyncResult OnBeginPersist(AsyncCallback callback, object state);
460 protected internal abstract void OnEndPersist(IAsyncResult result);
462 protected internal abstract void OnDisassociateKeys(ICollection<InstanceKey> keys);
464 protected internal abstract IAsyncResult OnBeginAssociateKeys(ICollection<InstanceKey> keys, AsyncCallback callback, object state);
465 protected internal abstract void OnEndAssociateKeys(IAsyncResult result);
467 internal IAsyncResult BeginFlushTrackingRecordsInternal(AsyncCallback callback, object state)
469 return OnBeginFlushTrackingRecords(callback, state);
472 internal void EndFlushTrackingRecordsInternal(IAsyncResult result)
474 OnEndFlushTrackingRecords(result);
477 protected void FlushTrackingRecords(TimeSpan timeout)
479 if (this.HasTrackingParticipant)
481 this.TrackingProvider.FlushPendingRecords(timeout);
485 protected IAsyncResult BeginFlushTrackingRecords(TimeSpan timeout, AsyncCallback callback, object state)
487 if (this.HasTrackingParticipant)
489 return this.TrackingProvider.BeginFlushPendingRecords(timeout, callback, state);
493 return new CompletedAsyncResult(callback, state);
497 protected void EndFlushTrackingRecords(IAsyncResult result)
499 if (this.HasTrackingParticipant)
501 this.TrackingProvider.EndFlushPendingRecords(result);
505 CompletedAsyncResult.End(result);
509 protected virtual IAsyncResult OnBeginFlushTrackingRecords(AsyncCallback callback, object state)
511 return this.Controller.BeginFlushTrackingRecords(ActivityDefaults.TrackingTimeout, callback, state);
514 protected virtual void OnEndFlushTrackingRecords(IAsyncResult result)
516 this.Controller.EndFlushTrackingRecords(result);
519 internal void NotifyPaused()
521 if (this.executor.State != ActivityInstanceState.Executing)
529 protected abstract void OnNotifyPaused();
531 internal void NotifyUnhandledException(Exception exception, Activity source, string sourceInstanceId)
533 if (this.controller.TrackingEnabled)
535 ActivityInfo faultSourceInfo = new ActivityInfo(source.DisplayName, source.Id, sourceInstanceId, source.GetType().FullName);
536 this.controller.Track(new WorkflowInstanceUnhandledExceptionRecord(this.Id, this.WorkflowDefinition.DisplayName, faultSourceInfo, exception, this.DefinitionIdentity));
539 OnNotifyUnhandledException(exception, source, sourceInstanceId);
542 protected abstract void OnNotifyUnhandledException(Exception exception, Activity source, string sourceInstanceId);
544 protected internal abstract void OnRequestAbort(Exception reason);
546 internal void OnDeserialized(bool hasTrackedStarted)
548 this.HasTrackedStarted = hasTrackedStarted;
551 void StartOperation(ref bool resetRequired)
553 StartReadOnlyOperation(ref resetRequired);
555 // isRunning can only flip to true by an operation and therefore
556 // we don't have to worry about this changing under us
557 if (this.executor.IsRunning)
559 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.RuntimeRunning));
563 void StartReadOnlyOperation(ref bool resetRequired)
565 bool wasPerformingOperation = false;
571 wasPerformingOperation = Interlocked.CompareExchange(ref this.isPerformingOperation, True, False) == True;
573 if (!wasPerformingOperation)
575 resetRequired = true;
579 if (wasPerformingOperation)
581 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.RuntimeOperationInProgress));
585 void FinishOperation(ref bool resetRequired)
589 this.isPerformingOperation = False;
593 internal void Abort(Exception reason)
597 this.isAborted = true;
600 this.abortedException = reason;
603 if (this.extensions != null)
605 this.extensions.Cancel();
608 if (this.controller.TrackingEnabled)
610 // During abort we only track this one record
613 string message = reason.Message;
614 if (reason.InnerException != null)
616 message = SR.WorkflowAbortedReason(reason.Message, reason.InnerException.Message);
618 this.controller.Track(new WorkflowInstanceAbortedRecord(this.Id, this.WorkflowDefinition.DisplayName, message, this.DefinitionIdentity));
628 this.abortStack = new StackTrace();
634 void ValidatePrepareForSerialization()
637 if (!this.Controller.IsPersistable)
639 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.PrepareForSerializationRequiresPersistability));
643 void ValidateScheduleResumeBookmark()
649 void ValidateGetBookmarks()
654 void ValidateGetMappedVariables()
659 void ValidatePauseWhenPersistable()
662 if (this.Controller.IsPersistable)
664 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.PauseWhenPersistableInvalidIfPersistable));
668 void Terminate(Exception reason)
670 // validate we're in an ok state
673 // terminate the runtime
674 this.executor.Terminate(reason);
676 // and track if necessary
681 void TrackCompletion()
683 if (this.controller.TrackingEnabled && !this.hasTrackedCompletion)
685 ActivityInstanceState completionState = this.executor.State;
687 if (completionState == ActivityInstanceState.Faulted)
689 Fx.Assert(this.executor.TerminationException != null, "must have a termination exception if we're faulted");
690 this.controller.Track(new WorkflowInstanceTerminatedRecord(this.Id, this.WorkflowDefinition.DisplayName, this.executor.TerminationException.Message, this.DefinitionIdentity));
692 else if (completionState == ActivityInstanceState.Closed)
694 this.controller.Track(new WorkflowInstanceRecord(this.Id, this.WorkflowDefinition.DisplayName, WorkflowInstanceStates.Completed, this.DefinitionIdentity));
698 Fx.AssertAndThrow(completionState == ActivityInstanceState.Canceled, "Cannot be executing a workflow instance when WorkflowState was completed.");
699 this.controller.Track(new WorkflowInstanceRecord(this.Id, this.WorkflowDefinition.DisplayName, WorkflowInstanceStates.Canceled, this.DefinitionIdentity));
701 this.hasTrackedCompletion = true;
707 // track if necessary
708 if (!this.hasTrackedResumed)
710 if (this.Controller.TrackingEnabled)
712 if (!this.HasTrackedStarted)
714 this.TrackingProvider.AddRecord(new WorkflowInstanceRecord(this.Id, this.WorkflowDefinition.DisplayName, WorkflowInstanceStates.Started, this.DefinitionIdentity));
715 this.HasTrackedStarted = true;
719 this.TrackingProvider.AddRecord(new WorkflowInstanceRecord(this.Id, this.WorkflowDefinition.DisplayName, WorkflowInstanceStates.Resumed, this.DefinitionIdentity));
722 this.hasTrackedResumed = true;
728 // validate we're in an ok state
733 // and let the scheduler go
734 this.executor.MarkSchedulerRunning();
737 void ScheduleCancel()
739 // validate we're in an ok state
744 this.executor.CancelRootActivity();
747 BookmarkResumptionResult ScheduleBookmarkResumption(Bookmark bookmark, object value)
749 // validate we're in an ok state
750 ValidateScheduleResumeBookmark();
754 return this.executor.TryResumeHostBookmark(bookmark, value);
757 BookmarkResumptionResult ScheduleBookmarkResumption(Bookmark bookmark, object value, BookmarkScope scope)
759 // validate we're in an ok state
760 ValidateScheduleResumeBookmark();
764 return this.executor.TryResumeBookmark(bookmark, value, scope);
768 void ThrowIfAborted()
770 if (this.isAborted || (this.executor != null && this.executor.IsAbortPending))
772 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.WorkflowInstanceAborted(this.Id)));
776 void ThrowIfNotIdle()
778 if (!this.executor.IsIdle)
780 throw FxTrace.Exception.AsError(new InvalidOperationException(SR.BookmarksOnlyResumableWhileIdle));
784 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.NestedTypesShouldNotBeVisible,
785 Justification = "these are effectively protected methods, but encapsulated in a struct to avoid naming conflicts")]
786 protected struct WorkflowInstanceControl
788 ActivityExecutor executor;
789 WorkflowInstance instance;
791 internal WorkflowInstanceControl(WorkflowInstance instance, ActivityExecutor executor)
793 this.instance = instance;
794 this.executor = executor;
797 public bool IsPersistable
801 return this.executor.IsPersistable;
805 public bool HasPendingTrackingRecords
809 return this.instance.HasTrackingParticipant && this.instance.TrackingProvider.HasPendingRecords;
813 public bool TrackingEnabled
817 return this.instance.HasTrackingParticipant && this.instance.TrackingProvider.ShouldTrackWorkflowInstanceRecords;
821 public WorkflowInstanceState State
825 WorkflowInstanceState result;
827 if (this.instance.isAborted)
829 result = WorkflowInstanceState.Aborted;
831 else if (!this.executor.IsIdle)
833 result = WorkflowInstanceState.Runnable;
837 if (this.executor.State == ActivityInstanceState.Executing)
839 result = WorkflowInstanceState.Idle;
843 result = WorkflowInstanceState.Complete;
851 public override bool Equals(object obj)
853 if (!(obj is WorkflowInstanceControl))
858 WorkflowInstanceControl other = (WorkflowInstanceControl)obj;
859 return other.instance == this.instance;
862 public override int GetHashCode()
864 return this.instance.GetHashCode();
867 public static bool operator ==(WorkflowInstanceControl left, WorkflowInstanceControl right)
869 return left.Equals(right);
872 public static bool operator !=(WorkflowInstanceControl left, WorkflowInstanceControl right)
874 return !left.Equals(right);
877 public ReadOnlyCollection<BookmarkInfo> GetBookmarks()
879 bool resetRequired = false;
883 this.instance.StartReadOnlyOperation(ref resetRequired);
885 this.instance.ValidateGetBookmarks();
887 return this.executor.GetAllBookmarks();
891 this.instance.FinishOperation(ref resetRequired);
895 public ReadOnlyCollection<BookmarkInfo> GetBookmarks(BookmarkScope scope)
897 bool resetRequired = false;
901 this.instance.StartReadOnlyOperation(ref resetRequired);
903 this.instance.ValidateGetBookmarks();
905 return this.executor.GetBookmarks(scope);
909 this.instance.FinishOperation(ref resetRequired);
913 public IDictionary<string, LocationInfo> GetMappedVariables()
915 bool resetRequired = false;
919 this.instance.StartReadOnlyOperation(ref resetRequired);
921 this.instance.ValidateGetMappedVariables();
923 IDictionary<string, LocationInfo> mappedLocations = this.instance.executor.GatherMappableVariables();
924 if (mappedLocations != null)
926 mappedLocations = new ReadOnlyDictionaryInternal<string, LocationInfo>(mappedLocations);
930 mappedLocations = WorkflowInstance.EmptyMappedVariablesDictionary;
932 return mappedLocations;
936 this.instance.FinishOperation(ref resetRequired);
942 bool resetRequired = false;
946 this.instance.StartOperation(ref resetRequired);
952 this.instance.FinishOperation(ref resetRequired);
958 public void RequestPause()
960 // No validations for this because we do not
961 // require calls to Pause to be synchronized
963 this.executor.PauseScheduler();
966 // Calls Pause when IsPersistable goes from false->true
967 public void PauseWhenPersistable()
969 bool resetRequired = false;
973 this.instance.StartOperation(ref resetRequired);
975 this.instance.ValidatePauseWhenPersistable();
977 this.executor.PauseWhenPersistable();
981 this.instance.FinishOperation(ref resetRequired);
985 public void ScheduleCancel()
987 bool resetRequired = false;
991 this.instance.StartOperation(ref resetRequired);
993 this.instance.ScheduleCancel();
997 this.instance.FinishOperation(ref resetRequired);
1001 public void Terminate(Exception reason)
1003 bool resetRequired = false;
1007 this.instance.StartOperation(ref resetRequired);
1009 this.instance.Terminate(reason);
1013 this.instance.FinishOperation(ref resetRequired);
1017 public BookmarkResumptionResult ScheduleBookmarkResumption(Bookmark bookmark, object value)
1019 bool resetRequired = false;
1023 this.instance.StartOperation(ref resetRequired);
1025 return this.instance.ScheduleBookmarkResumption(bookmark, value);
1029 this.instance.FinishOperation(ref resetRequired);
1033 public BookmarkResumptionResult ScheduleBookmarkResumption(Bookmark bookmark, object value, BookmarkScope scope)
1035 bool resetRequired = false;
1039 this.instance.StartOperation(ref resetRequired);
1041 return this.instance.ScheduleBookmarkResumption(bookmark, value, scope);
1045 this.instance.FinishOperation(ref resetRequired);
1051 bool resetRequired = false;
1055 this.instance.StartOperation(ref resetRequired);
1059 this.executor.Dispose();
1061 this.instance.Abort(null);
1065 this.instance.FinishOperation(ref resetRequired);
1069 public void Abort(Exception reason)
1071 bool resetRequired = false;
1075 this.instance.StartOperation(ref resetRequired);
1079 this.executor.Abort(reason);
1081 this.instance.Abort(reason);
1085 this.instance.FinishOperation(ref resetRequired);
1089 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
1090 Justification = "Only want to allow WorkflowInstanceRecord subclasses for WorkflowInstance-level tracking")]
1091 public void Track(WorkflowInstanceRecord instanceRecord)
1093 if (this.instance.HasTrackingParticipant)
1095 this.instance.TrackingProvider.AddRecord(instanceRecord);
1099 public void FlushTrackingRecords(TimeSpan timeout)
1101 this.instance.FlushTrackingRecords(timeout);
1104 public IAsyncResult BeginFlushTrackingRecords(TimeSpan timeout, AsyncCallback callback, object state)
1106 return this.instance.BeginFlushTrackingRecords(timeout, callback, state);
1109 public void EndFlushTrackingRecords(IAsyncResult result)
1111 this.instance.EndFlushTrackingRecords(result);
1114 public object PrepareForSerialization()
1116 bool resetRequired = false;
1120 this.instance.StartReadOnlyOperation(ref resetRequired);
1122 this.instance.ValidatePrepareForSerialization();
1124 return this.executor.PrepareForSerialization();
1128 this.instance.FinishOperation(ref resetRequired);
1132 public ActivityInstanceState GetCompletionState()
1134 return this.executor.State;
1137 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
1138 Justification = "Arch approved design. Requires the out argument for extra information provided")]
1139 public ActivityInstanceState GetCompletionState(out Exception terminationException)
1141 terminationException = this.executor.TerminationException;
1142 return this.executor.State;
1145 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters,
1146 Justification = "Arch approved design. Requires the out argument for extra information provided")]
1147 public ActivityInstanceState GetCompletionState(out IDictionary<string, object> outputs, out Exception terminationException)
1149 outputs = this.executor.WorkflowOutputs;
1150 terminationException = this.executor.TerminationException;
1151 return this.executor.State;
1154 public Exception GetAbortReason()
1156 return this.instance.abortedException;