c# - WF4 : Workflow stay locked

标签 c# .net c#-4.0 workflow-foundation-4

我有一个使用 WorkflowApplication 在 IIS 中托管 WF4 工作流的应用程序

工作流程由用户定义(使用重新托管的工作流程设计器),并且 xml 存储在数据库中。然后,根据使用应用程序的用户操作,在数据库中选择一个 xml,并创建/恢复工作流程。

我的问题是:当工作流程到达书签并进入空闲状态时,它会保持锁定状态一段不同的时间。然后,如果用户尝试针对此工作流程执行另一个操作,我会收到此异常:

The execution of an InstancePersistenceCommand was interrupted because the instance '52da4562-896e-4959-ae40-5cd016c4ae79' is locked by a different instance owner. This error usually occurs because a different host has the instance loaded. The instance owner ID of the owner or host with a lock on the instance is '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; 
}

对于我需要的每个 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);

抛出上面指定的“锁定”异常。 如果我等待几分钟,然后重试,效果很好。

我读到一篇文章 here 说我们需要设置一个所有者。 因此,我还尝试使用静态 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;

但是我有这样的异常(exception):

The execution of an InstancePersistenceCommand was interrupted because the instance owner registration for owner ID '9efb4434-8560-469f-9d03-098a2d48821e' has become invalid. This error indicates that the in-memory copy of all instances locked by this owner have become stale and should be discarded, along with the InstanceHandles. Typically, this error is best handled by restarting the host.

有谁知道如何确保在卸载工作流时立即释放工作流上的锁定? 我看到一些 post 使用 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 回调。

关于c# - WF4 : Workflow stay locked,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12797975/

相关文章:

c# - 附件未出现在 Outlook 2016 中

.net - 如何控制将哪个 SQL 提供程序用于数据库连接?

ios - MonoTouch 在后台加载图像

c# - 如何使用 DropDownList.text 选择

c# - C# 中是否有 <key, value, value> 字典类型?

c# - 更新语句不更新我的数据

c# - Windows 窗体触地事件

c# - 修复 "Improper Restriction of xml external entity reference"的最佳方法是什么?

c# - WebClient上传文件错误

css - 如何在 ASP.NET Web 窗体中渲染 CSS 内联