WF4:工作流保持锁定状态
我有一个使用WorkflowApplication在IIS中托管WF4工作流的应用程序
工作流由用户定义(使用重新主办的工作流设计器),并将xml存储在数据库中。 然后,根据使用应用程序的用户操作,在数据库中选择xml并创建/恢复工作流程。
我的问题是:当工作流程达到书签并闲置时,它会保持锁定不同的时间。 然后,如果用户尝试对此工作流程进行其他操作,我得到以下异常:
InstancePersistenceCommand的执行被中断,因为实例“52da4562-896e-4959-ae40-5cd016c4ae79”被另一个实例所有者锁定。 通常会发生此错误,因为不同的主机已加载实例。 拥有实例锁的所有者或主机的实例所有者ID是'd7339374-2285-45b9-b4ea-97b18c968c19'。
现在是时候写一些代码了
当我的工作流程闲置时,我指定它应该被卸载:
private PersistableIdleAction handlePersistableIdle(WorkflowApplicationIdleEventArgs arg)
{
this.Logger.DebugFormat("Workflow '{1}' is persistableIdle on review '{0}'", arg.GetReviewId(), arg.InstanceId);
return PersistableIdleAction.Unload;
}
我需要Foreach WorkflowApplication,我创建一个新的SqlWorkflowInstanceStore:
var store = new SqlWorkflowInstanceStore(this._connectionString);
store.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(5);
store.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry;
以下是我的WorkflowApplication创建过程
WorkflowApplication wfApp = new WorkflowApplication(root.RootActivity);
wfApp.Extensions.Add(...);
wfApp.InstanceStore = this.createStore();
wfApp.PersistableIdle = this.handlePersistableIdle;
wfApp.OnUnhandledException = this.handleException;
wfApp.Idle = this.handleIdle;
wfApp.Unloaded = this.handleUnloaded;
wfApp.Aborted = this.handleAborted;
wfApp.SynchronizationContext = new CustomSynchronizationContext();
return wfApp;
然后我调用Run方法启动它。 一些解释:
- root.RootActivity:它是根据存储在数据库中的工作流XML创建的活动
- CustomSynchronizationContext:处理授权的同步上下文
- 在handleUnloaded方法中,我记录了卸载工作流的时间,并且我看到工作流在下一个用户操作之前被正确卸载,但似乎工作流在卸载后保持锁定状态(?)
之后,当我需要恢复工作流程时,我会按照与我打电话相同的方式创建工作流程:
wfApp.Load(workflowInstanceId);
这会抛出上面指定的“锁定”异常。 如果我等几分钟,然后再试一次,它可以正常工作。
我在这里看到一篇文章说我们需要设置一个所有者。 所以我也尝试使用静态SqlWorkflowInstanceStore与所有者使用此代码设置:
if (_sqlWorkflowInstanceStore != null)
return _sqlWorkflowInstanceStore;
lock (_mutex)
{
if (_sqlWorkflowInstanceStore != null)
return _sqlWorkflowInstanceStore;
// Configure store
_sqlWorkflowInstanceStore = new SqlWorkflowInstanceStore(this._connectionString);
_sqlWorkflowInstanceStore.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(5);
_sqlWorkflowInstanceStore.InstanceLockedExceptionAction = InstanceLockedExceptionAction.BasicRetry;
// Set owner - Store will be read-only beyond this point and will not be configurable anymore
var handle = _sqlWorkflowInstanceStore.CreateInstanceHandle();
var view = _sqlWorkflowInstanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(5));
handle.Free();
_sqlWorkflowInstanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
return _sqlWorkflowInstanceStore;
但是,我有这种例外:
InstancePersistenceCommand的执行被中断,因为所有者ID“9efb4434-8560-469f-9d03-098a2d48821e”的实例所有者注册已失效。 此错误表示由此所有者锁定的所有实例的内存中副本已过时,应与InstanceHandles一起丢弃。 通常,最好通过重新启动主机来处理此错误。
有谁知道如何确保卸载工作流时立即释放对工作流的锁定? 我看到一些职位使用WorkflowServiceHost(使用WorkflowIdleBehavior)执行此操作,但在这里我没有使用WorkflowServiceHost,我正在使用WorkflowApplication
感谢您的任何帮助!
我怀疑问题出在SqlWorkflowInstanceStore的InstanceOwner上。 它不会被删除,因此工作流需要等待上一个的所有权才能超时。
创建一个实例所有者
var instanceStore = new SqlWorkflowInstanceStore(connStr);
var instanceHandle = instanceStore.CreateInstanceHandle();
var createOwnerCmd = new CreateWorkflowOwnerCommand();
var view = instanceStore.Execute(instanceHandle, createOwnerCmd, TimeSpan.FromSeconds(30));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
删除实例所有者
var deleteOwnerCmd = new DeleteWorkflowOwnerCommand();
instanceStore.Execute(instanceHandle, deleteOwnerCmd, TimeSpan.FromSeconds(30));
另一个可能的问题是,当工作流程中止Unloaded回调不被调用时。
链接地址: http://www.djcxy.com/p/95891.html