/// <summary> /// 创建工作流 /// </summary> /// <param name="flow"></param> /// <returns></returns> public static Guid CreateWorkflow(string OrderOID) { InstanceHandle instanceHandle = InstanceStoreObj.CreateInstanceHandle(); InstanceView view = InstanceStoreObj.Execute(instanceHandle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30)); InstanceStoreObj.DefaultInstanceOwner = view.InstanceOwner; IDictionary <string, object> input = new Dictionary <string, object> { { "OrderOID", OrderOID } }; //WorkflowApplication application = new WorkflowApplication(new AuthFlow(),input); WorkflowApplication application = new WorkflowApplication(new WorkflowService.OrderFlow.OrderFlow(), input); application.InstanceStore = InstanceStoreObj; application.PersistableIdle = (e) => { return(PersistableIdleAction.Unload); }; application.Unloaded = (e) => { //PersistableIdleAction.Unload; }; application.Run(); var deleteOwnerCmd = new DeleteWorkflowOwnerCommand(); //InstanceStoreObj.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30)); InstanceStoreObj = null; return(application.Id); }
/// <summary> /// Removes the store owner upon application shut down. This allows another service to recover workflows from other machines. /// This should be called from a dispose method in your application /// </summary> /// <param name="timeout"></param> public static void RemoveStoreOwner(TimeSpan timeout) { var deleteOwner = new DeleteWorkflowOwnerCommand(); InstanceHandle handle = Store.CreateInstanceHandle(); Store.Execute(handle, deleteOwner, timeout); handle.Free(); }
public void ResumeWorkFlow(BusinessObject.DtoModels.Game game) { Exception exception = new Exception(); Guid workflowInstanceID = game.InstanceId; SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(databaseConnection); store.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry; store.HostLockRenewalPeriod = TimeSpan.FromSeconds(2); InstanceHandle instanceHandle = store.CreateInstanceHandle(); CreateWorkflowOwnerCommand createOwnerCmd = new CreateWorkflowOwnerCommand(); InstanceView view = store.Execute(instanceHandle, createOwnerCmd, TimeSpan.FromSeconds(10)); store.DefaultInstanceOwner = view.InstanceOwner; WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(workflowInstanceID, store); AutoResetEvent syncEvent = new AutoResetEvent(false); WorkflowApplication wfApplication = new WorkflowApplication(new FlowchartNumberGuessWorkflow(), instance.DefinitionIdentity); wfApplication.PersistableIdle = (e) => PersistableIdleAction.Unload; wfApplication.Unloaded = (e) => { syncEvent.Set(); }; wfApplication.OnUnhandledException = (e) => { exception = e.UnhandledException; syncEvent.Set(); return(UnhandledExceptionAction.Cancel); }; wfApplication.Load(instance); BookmarkResumptionResult result = wfApplication.ResumeBookmark("Decision", game); syncEvent.WaitOne(); if (exception.Message != string.Empty && exception.StackTrace != null) { throw exception; } DeleteWorkflowOwnerCommand deleteOwnerCmd = new DeleteWorkflowOwnerCommand(); store.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(10)); }
private static void DeleteWorkflowInstanceOwner(InstanceStore store, InstanceOwner owner, Guid instanceId) { InstanceHandle handle = null; var command = new DeleteWorkflowOwnerCommand(); try { handle = store.CreateInstanceHandle(owner, instanceId); store.Execute(handle, command, TimeSpan.FromMinutes(1.0)); store.DefaultInstanceOwner = null; } finally { handle?.Free(); } }
private static void DestroyInstanceOwner(WorkflowApplication wfApp, InstanceHandle instanceHandle) { try { if (instanceHandle.IsValid) { //WriteDebug("DestroyInstanceOwner: " + wfApp.Id); var deleteOwnerCmd = new DeleteWorkflowOwnerCommand(); wfApp.InstanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30)); wfApp.InstanceStore.DefaultInstanceOwner = null; } else { Debug.WriteLine("DestroyInstanceOwner: HANDLE IS FREED: " + wfApp.Id); } } catch (Exception ex) { Debug.WriteLine("DestroyInstanceOwner", ex); throw ex; } }
protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state) { SaveWorkflowCommand save = command as SaveWorkflowCommand; if (save != null) { lock (FileStore.s_thisLock) { ProcessSaveCommand(context, save); } } LoadWorkflowCommand load = command as LoadWorkflowCommand; if (load != null) { lock (FileStore.s_thisLock) { ProcessLoadCommand(context, load); } } LoadWorkflowByInstanceKeyCommand loadByKey = command as LoadWorkflowByInstanceKeyCommand; if (loadByKey != null) { lock (FileStore.s_thisLock) { ProcessLoadByKeyCommand(context, loadByKey); } } if (save != null || load != null || loadByKey != null) { return(new CompletedAsyncResult(callback, state)); } CreateWorkflowOwnerCommand createOwner = command as CreateWorkflowOwnerCommand; if (createOwner != null) { Guid ownerId = Guid.NewGuid(); Owner owner = new Owner(); lock (s_thisLock) { owner.Id = ownerId; owner.LockToken = Guid.NewGuid(); owner.Metadata = new PropertyBag(createOwner.InstanceOwnerMetadata); PersistenceItemManager.SaveToFile <Owner>(owner); } context.BindInstanceOwner(ownerId, owner.LockToken); context.BindEvent(HasRunnableWorkflowEvent.Value); return(new CompletedAsyncResult(callback, state)); } DeleteWorkflowOwnerCommand deleteOwner = command as DeleteWorkflowOwnerCommand; if (deleteOwner != null) { Guid ownerId = context.InstanceView.InstanceOwner.InstanceOwnerId; lock (FileStore.s_thisLock) { Owner owner = PersistenceItemManager.Load <Owner>(ownerId); if (owner != null && owner.LockToken == context.LockToken) { PersistenceItemManager.Remove <Owner>(ownerId); } } context.InstanceHandle.Free(); return(new CompletedAsyncResult(callback, state)); } return(base.BeginTryCommand(context, command, timeout, callback, state)); }
/// <summary> /// Starts processing the given activity via the WorkflowApplication. /// </summary> /// <param name="command">The command to be ran.</param> /// <param name="firstParameter">The first parameter to include (if any).</param> /// <param name="secondParameter">The second parameter to include (if any).</param> /// <param name="thirdParameter">The third parameter to include (if any).</param> private void StartWorkflowScience(string command, string firstParameter, string secondParameter, string thirdParameter /* future use */) { // Now stage the WorkflowApplication, using the SQL instance, wrapped in using to dispose all of the things when done. using (AutoResetEvent syncEvent = new AutoResetEvent(false)) { // NOTE: If the string doesn't - explicitly - match, the .ctor() of the // SwedishCodeActivity will throw, since the string is the key. Also, // no boxing/unboxing required for Dictionary<T,T>; which saves overhead. Dictionary <string, SwedishCodeActivity <object> > newDictionary = new Dictionary <string, SwedishCodeActivity <object> > { // See the 'Activities' folder for examples of Activities that you can use here. { "CheckFreeDiskSpaceActivity", new CheckFreeDiskSpaceActivity() }, { "CopyFilesActivity", new CopyFilesActivity() }, { "CopyNIsAndDLLsActivity", new CopyImagesAndLibrariesActivity() }, { "DateTimeActivity", new UtcDateTimeActivity() }, { "DumpProcessThreadsActivity", new DumpProcessThreadsActivity() }, { "FileExistsActivity", new CheckIfFileExistsActivity() }, { "ForceBlueScreenActivity", new ForceBlueScreenActivity() }, { "GetLoggedOnUsersActivity", new GetCurrentLoggedOnUsersActivity() }, { "GetOsFileVersionActivity", new GetOsFileVersionActivity() }, { "GetProcessIdActivity", new GetProcessIdsActivity() }, { "GetSystemUptimeActivity", new GetSystemUptimeActivity() }, { "GetTimeSkewActivity", new GetSystemTimeSkewActivity() }, { "InstallSysInternalsActivity", new InstallSysInternalsActivity() }, { "ModifyConfigurationFileActivity", new EditConfigurationFileActivity() }, { "PingActivity", new PingResponseActivity() }, { "PortConnectivityActivity", new PortConnectivityActivity() }, { "ReadFileContentsActivity", new ReadFileContentsActivity() }, { "RenameMachineActivity", new RenameMachineActivity() }, { "RestartServiceActivity", new RestartServiceActivity() }, { "SetSymbolsEnvironmentPath", new SetSymbolServerEnvironmentPathActivity() }, { "StartSecureDeleteActivity", new StartSecureDeleteActivity() }, { "WindowsUpdateActivity", new WindowsUpdateActivity() }, { "WebStringActivity", new WebStringActivity() } }; SwedishCodeActivity <object> newSwedishCodeActivity = (SwedishCodeActivity <object>)newDictionary[command]; if (!string.IsNullOrWhiteSpace(firstParameter)) { newSwedishCodeActivity.FirstInArgument = firstParameter; } if (!string.IsNullOrWhiteSpace(secondParameter)) { newSwedishCodeActivity.SecondInArgument = secondParameter; } if (!string.IsNullOrWhiteSpace(thirdParameter)) { newSwedishCodeActivity.ThirdInArgument = thirdParameter; } SqlWorkflowInstanceStore newSqlWorkflowInstanceStore = new SqlWorkflowInstanceStore("Server=192.168.0.252,1433\\SQL2008EXPRESS;Initial Catalog=WorkflowInstanceStore;Integrated Security=SSPI") { HostLockRenewalPeriod = TimeSpan.FromSeconds(1), InstanceCompletionAction = InstanceCompletionAction.DeleteNothing, InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry, RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(1) // Minimum allowed value. }; InstanceHandle workflowInstanceStoreHandle = newSqlWorkflowInstanceStore.CreateInstanceHandle(); CreateWorkflowOwnerCommand createWorkflowOwnerCommand = new CreateWorkflowOwnerCommand(); InstanceView newInstanceView = newSqlWorkflowInstanceStore.Execute(workflowInstanceStoreHandle, createWorkflowOwnerCommand, TimeSpan.FromSeconds(30)); newSqlWorkflowInstanceStore.DefaultInstanceOwner = newInstanceView.InstanceOwner; WorkflowApplication newWorkflowApplication = new WorkflowApplication(newSwedishCodeActivity, new WorkflowIdentity { // The Dictionary will throw for non-found key before we ever get here, so no need to validate input. Name = command, Version = new Version(0, 1, 0, 0) }) { InstanceStore = newSqlWorkflowInstanceStore, SynchronizationContext = SynchronizationContext.Current }; newWorkflowApplication.Persist(); ResultObject = new object(); newWorkflowApplication.Completed += delegate(WorkflowApplicationCompletedEventArgs e) { if (e.CompletionState == ActivityInstanceState.Faulted) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has faulted.\nException: {e.TerminationException.GetType().FullName}\nMessage:{e.TerminationException.Message}"); syncEvent.Set(); } else if (e.CompletionState == ActivityInstanceState.Canceled) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been canceled."); syncEvent.Set(); } else { // Since the result can be *anything*, let's not treat it like a string. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} completed. Result: {e.Outputs["Result"]}"); ResultObject = e.Outputs["Result"]; syncEvent.Set(); } }; newWorkflowApplication.Aborted = delegate(WorkflowApplicationAbortedEventArgs e) { // The workflow aborted, so let's find out why. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been aborted.\nException: {e.Reason.GetType().FullName}\nMessage:{e.Reason.Message}"); syncEvent.Set(); }; newWorkflowApplication.Idle = delegate(WorkflowApplicationIdleEventArgs e) { // TODO: [FUTURE] Need to handle future persistence maintenance. EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered the Idle state."); syncEvent.Set(); }; newWorkflowApplication.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has entered PersistableIdle."); syncEvent.Set(); // Runtime will persist. return(PersistableIdleAction.Persist); }; newWorkflowApplication.Unloaded = delegate(WorkflowApplicationEventArgs e) { EventLog.WriteEntry("Felsökning.Tomte.AdminService", $"Workflow {e.InstanceId} has been unloaded."); syncEvent.Set(); }; newWorkflowApplication.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e) { // Log the unhandled exception. EventLog.WriteEntry("Felsökning.Tomte.AdminService", !string.IsNullOrWhiteSpace(e.UnhandledException.InnerException?.Message) ? $"Workflow {e.InstanceId} has reached an AggregateException in OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.InnerException.GetType().FullName}\nMessage: {e.UnhandledException.InnerException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}" : $"Workflow {e.InstanceId} has reached OnUnhandledException.\nException Source: {e.ExceptionSource.DisplayName}\nException Instance ID: {e.ExceptionSourceInstanceId}\nException: {e.UnhandledException.GetType().FullName}\nMessage: {e.UnhandledException.Message}\nFirstArgument: {firstParameter}\nSecondArgument: {secondParameter}"); syncEvent.Set(); // Instruct the runtime to terminate the workflow. // The other viable choices here are 'Abort' or 'Cancel' return(UnhandledExceptionAction.Terminate); }; newWorkflowApplication.Run(); // Because a new thread is spawned, we need to wait for it to complete before we can move on. syncEvent.WaitOne(); // Instance MUST be unloaded to update the SQL record. One would think this would happen on the overridden delegate methods (e.g.: Completed,OnUnhandledException, etc.) // but testing has proven this to not be the case. newWorkflowApplication.Unload(TimeSpan.FromSeconds(30)); // Now, we dump the instance owner. DeleteWorkflowOwnerCommand newDeleteWorkflowOwnerCommand = new DeleteWorkflowOwnerCommand(); newSqlWorkflowInstanceStore.Execute( workflowInstanceStoreHandle, newDeleteWorkflowOwnerCommand, TimeSpan.FromSeconds(30)); } GC.Collect(); }
private bool DeleteWorkflowOwner(InstancePersistenceContext context, DeleteWorkflowOwnerCommand command) { return(true); }
/// <summary> /// Handles a <see cref="DeleteWorkflowOwnerCommand"/>. /// </summary> /// <param name="context"></param> /// <param name="command"></param> Task <bool> DeleteWorkflowOwnerCommand(InstancePersistenceContext context, DeleteWorkflowOwnerCommand command) { return(Task.FromResult(true)); }