WorkflowApplication成为孤儿工作流状态[S]

问题描述 投票:1回答:1

我有一个Windows服务包一个WCF服务,包装一个WorkflowApplication这个调用活动。 WCF客户端被包裹在调用对给定服务器PowerShell命令。最终到终端的工作流程执行完美,因为这证明了:

Get-PingResponse -Server 192.168.0.252 -Target 8.8.8.8
Workflow 33d9bd45-663a-4f95-b487-cf2f63081881 completed. Result: True

然而,笔者认为,因为活动/ WorkflowApplication轮询间隔命中之前完成(最小运行间隔不能小于1秒),则WorkflowApplication孤儿更新SQL条目。

33D9BD45-663A-4F95-B487-CF2F63081881    NULL    2019-02-07 10:57:43.880 2019-02-07 10:57:43.867 NULL    NULL    NULL        NULL    KALLIX  Executing   1   0   0   1   NULL    NULL    0x1F8B0800000000000400B5565D6FDB36149DF2D1D84ED2A50186ED69308ABD6CB32539F26780CCCCB26E3096A4811DA4018A7AA5242AE52C912E49D955860143036CF909C9D37EE4FEC02859921B0746822AB55F04823CF7DE73CEBD24281C313A444C60C4412EFE0EC0D35F5170025D1F1D41CC9E3BA787D0439004C7C11091C383F1F8E410B6173AF6FBF652B874F55F2FE00279EA1E755D64094C09577F4104316CA91F22BDDE7AF932DE7AEAB9EA3E266FD508BB549C592E154F10E31268A7AAEAE1BF54DCF35DE133B443902F18744BC523DF74B125F18FE900911DB3D18035AB56AFB48C2AD29BAD57A524D673F3779955A9E8718B32179B0F01FEAA9DDBE51C79A61BFC95FBF18D10C36D4DE3D61BE441AEDA50408B1299A62554CACEB42D5DAF6A7A439BCF535EC1DFC628E3F1581D1BC9B98A767AB0DF8B80CB9870018985F2CAB93113D2C316A39C3A42B5A817C633B48AAEF5A404D0C5E730D444038B031484BA5D2EB4577F96B95116497AB501B7438593DD88C5BA7E3DA38A3AB32BA5E0AA3BB3F30128CE2BB03153E45DBC26A6024B44961355BA1897B21E27D8130C93B30FC5FBECFAA73F7C46B663F1CA299365C9E4767C6C57BA7A84C32ED1A421B561DA347FBEA06CE0B874AC80E551D83151D4A538EA77B78EAB5D9F08EC2135460C9EBD43962F9598A674757CEBD447D069544CC768D6EAD036EA5564D4C0469269C74632053171C272AE7537C9D249FA5662DE291552A17B1CBEE1FCE9E1FE54A347D76B4752948491FECA68D2FB11952BD72BBA5A0947800236D312E246E8D819D2BFFEC630EC9669576BE57ADD80E5AAD3AA95CD6AB351B69C2DA76EE8CD4AB3590105986A1F2594CB10127C99F698DD896BD8C75CF00839DF5EEAE173F45EF2BA7BB72873784D0CD62F267C26810EE0504DBEC3A051CC022870C9BD8B3A7280472BABB1779FDE7261EAD904E5537BF63E4CCFA1017C3165FA1919614689276D1F55B8761FDC399EEFE75D6A45E374A2D9FA44B3CBE5BC627E7C33FC96DB8F51D54582DDBF958758501490377D1EEC51397232947C011670963EBB00CB742C1F0311F78F332472734C801CF74D791F0A940572B38B387547E1F861677E6811AEF40B69EBD851D29FFFAB843FB06A523AF0201B1C9C4DAAD9C8101A3C22E89DE8D8170A78EC422E92A6CA34D32EC01AA334C56A2F769173B93A3155865CA593C2EBD1F6DD58C62719C0C0BA831917E12C4F87CE663C747EB83D74E65D98DF4F6E4ED495F5A658D317C927B9441F66326FC4374A90487E4326A5FF15436F7DCC10EF059E49DDC8A17EF882FB27B2A1F23F5068CE26B50B0000    NULL    PingActivity    NULL    0   0   1   0 

在主/理论,因为WorkflowApplication.Completed被调用时,其应更新为特定实例的SQL记录;然而,这似乎并没有被存在的 - 作为记录的状态(上图)示出了。

最终的目标是 - 最终 - 该记录被更新,以反映工作流的状态。各州没有SQL行中被改变的记录,因此所有执行只是显示“执行” - 即使是断陷工作流程。

此前,我曾与持久性写作进入SQL表的问题,而这是通过调用persist()在WorkflowApplication解决。见here

        SqlWorkflowInstanceStore newSqlWorkflowInstanceStore = new SqlWorkflowInstanceStore("Server=.\\SQL2008EXPRESS;Initial Catalog=WorkflowInstanceStore;Integrated Security=SSPI")
                                                        {
                                                            HostLockRenewalPeriod = TimeSpan.FromSeconds(5),
                                                            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;

        // The Dictionary will throw for non-found key before we ever get here, so no need to validate input.
        WorkflowIdentity newWorkflowIdentity = new WorkflowIdentity
                                                   {
                                                       Name = command,
                                                       Version = new Version(0, 1, 0, 0)
                                                   };

        // Now stage the WorkflowApplication, using the SQL instance.
        AutoResetEvent syncEvent = new AutoResetEvent(false);
        WorkflowApplication newWorkflowApplication = new WorkflowApplication(newSwedishCodeActivity, newWorkflowIdentity)
                                                         {
                                                             InstanceStore = newSqlWorkflowInstanceStore
                                                         };
        newWorkflowApplication.Persist();
        this.Result = new object();
        newWorkflowApplication.Completed += delegate(WorkflowApplicationCompletedEventArgs e)
        {
            if (e.CompletionState == ActivityInstanceState.Faulted)
            {
                this.Result = $"Workflow {e.InstanceId} has faulted.\nException: {e.TerminationException.GetType().FullName}\nMessage:{e.TerminationException.Message}";
                syncEvent.Set();
            }
            else if (e.CompletionState == ActivityInstanceState.Canceled)
            {
                this.Result = $"Workflow {e.InstanceId} has been canceled.";
                syncEvent.Set();
            }
            else
            {
                this.Result = $"Workflow {e.InstanceId} completed. Result: {e.Outputs["Result"]}";
                syncEvent.Set();
            }
        };

        newWorkflowApplication.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
        {
            // The workflow aborted, so let's find out why.
            this.Result = $"Workflow {e.InstanceId} has been aborted.\nException: {e.Reason.GetType().FullName}\nMessage:{e.Reason.Message}";
            syncEvent.Set();
        };

        newWorkflowApplication.Idle = delegate(WorkflowApplicationIdleEventArgs e)
        {
            this.Result = $"Workflow {e.InstanceId} has entered the Idle state.";
            syncEvent.Set();
        };

        newWorkflowApplication.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
        {
            this.Result = $"Workflow {e.InstanceId} has entered PersistableIdle.";
            syncEvent.Set();

            // Runtime will persist.
            return PersistableIdleAction.Persist;
        };

        newWorkflowApplication.Unloaded = delegate(WorkflowApplicationEventArgs e)
        {
            syncEvent.Set();
        };

        newWorkflowApplication.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
        {
            // Display the unhandled exception.
            this.Result = $"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}";
            syncEvent.Set();

            // Instruct the runtime to terminate the workflow.
            // The other viable choices here are 'Abort' or 'Cancel'
            return UnhandledExceptionAction.Terminate;
        };

        newWorkflowApplication.Run();
        syncEvent.WaitOne();

        DeleteWorkflowOwnerCommand newDeleteWorkflowOwnerCommand = new DeleteWorkflowOwnerCommand();
        newSqlWorkflowInstanceStore.Execute(
           workflowInstanceStoreHandle,
           newDeleteWorkflowOwnerCommand,
           TimeSpan.FromSeconds(30));

预期的结果是,当委托被调用WorkflowApplication.Completed,其应于InstanceStore更新实例的SQL记录。

实际的结果是,记录是孤儿,留下了“执行”状态。

c# workflow-foundation-4 workflow-foundation
1个回答
1
投票

找到了答案:工作流实例必须卸载,以便为国家在SQL记录进行更新。

newWorkflowApplication.Unload(TimeSpan.FromSeconds(30));

这里离开这个,万一别人永远运行到这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.