3

我有一个 Windows 服务,正在运行工作流。工作流是从数据库加载的 XAML(用户可以使用重新托管的设计器定义自己的工作流)。它配置了一个 SQLWorkflowInstanceStore 实例,以便在空闲时保持工作流。(它基本上源自 Microsoft 的 WCF/WF 示例中的 \ControllingWorkflowApplications 中的示例代码)。

但有时我会收到如下错误:

System.Runtime.DurableInstancing.InstanceOwnerException:InstancePersistenceCommand 的执行被中断,因为所有者 ID 'a426269a-be53-44e1-8580-4d0c396842e8' 的实例所有者注册已失效。此错误表明此所有者锁定的所有实例的内存副本已过时,应连同 InstanceHandles 一起丢弃。通常,最好通过重新启动主机来处理此错误。

我一直在努力寻找原因,但很难在开发中重现,但在生产服务器上,我偶尔会得到它。我发现一个提示:当我查看 LockOwnersTable 时,我发现 LockOnwersTable lockexpiration 设置为 01/01/2000 0:0:0 并且它不再更新,而在正常情况下,应该根据每 x 秒更新一次主机锁更新期...

那么,为什么 SQLWorkflowInstanceStore 会停止更新这个 LockExpiration 以及如何检测它的原因?

4

3 回答 3

1

这是一个旧线程,但我偶然发现了同样的问题。

Damir's Corner建议在调用实例存储之前检查实例句柄是否仍然有效。我在此引用整篇文章:

Workflow Foundation 的某些方面仍然缺乏文档记录;持久性框架就是其中之一。以下代码段通常用于设置实例存储:

var instanceStore = new SqlWorkflowInstanceStore(connectionString);
instanceStore.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
var instanceHandle = instanceStore.CreateInstanceHandle();
var view = instanceStore.Execute(instanceHandle, 
    new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
instanceStore.DefaultInstanceOwner = view.InstanceOwner;

很难找到所有这一切的详细解释。老实说,通常没有必要。至少不会,直到您开始遇到问题,例如 InstanceOwnerException:

InstancePersistenceCommand 的执行被中断,因为所有者 ID '9938cd6d-a9cb-49ad-a492-7c087dcc93af' 的实例所有者注册已失效。此错误表明此所有者锁定的所有实例的内存副本已过时,应连同 InstanceHandles 一起丢弃。通常,最好通过重新启动主机来处理此错误。

该错误与 HostLockRenewalPeriod 属性密切相关,该属性定义了获得的实例句柄在不被更新的情况下有效的时间。如果您在实例化具有有效实例句柄的实例存储时尝试监控数据库,您会注意到 [System.Activities.DurableInstancing].[ExtendLock] 被定期调用。这个存储过程负责更新句柄。如果由于某种原因未能在指定的 HostLockRenewalPeriod 内调用,则在尝试持久化工作流时将引发上述异常。一个典型的原因是由于维护或网络问题而暂时无法访问数据库。这不是经常发生的事情,但如果你有一个长期存在的实例存储,它就一定会发生,例如

幸运的是,一旦您知道了问题的原因,解决问题并不是那么困难。在使用实例存储之前,您应该始终检查句柄是否仍然有效;并更新它,如果不是:

if (!instanceHandle.IsValid)
{
    instanceHandle = instanceStore.CreateInstanceHandle();
    var view = instanceStore.Execute(instanceHandle, 
        new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
    instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}

错误消息表明,它绝对比重新启动主机的侵入性更小。

于 2018-03-13T15:25:06.080 回答
1

发生这种情况是因为有程序在后台运行,并试图每 30 秒延长一次实例存储的锁定,并且似乎一旦连接到 SQL 服务失败,它就会将该实例存储标记为无效。如果从 [LockOwnersTable] 表中删除实例存储记录,您会看到相同的行为。建议的解决方案是当此异常触发时,您需要释放旧实例存储并初始化一个新实例存储

public class WorkflowInstanceStore : IWorkflowInstanceStore, IDisposable
{
    public WorkflowInstanceStore(string connectionString)
    {
        _instanceStore = new SqlWorkflowInstanceStore(connectionString);

        InstanceHandle handle = _instanceStore.CreateInstanceHandle();
        InstanceView view = _instanceStore.Execute(handle, 
            new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
        handle.Free();

        _instanceStore.DefaultInstanceOwner = view.InstanceOwner;
    }

    public InstanceStore Store
    {
        get { return _instanceStore; }
    }

    public void Dispose()
    {
        if (null != _instanceStore)
        {
            var deleteOwner = new DeleteWorkflowOwnerCommand();
            InstanceHandle handle = _instanceStore.CreateInstanceHandle();
            _instanceStore.Execute(handle, deleteOwner, TimeSpan.FromSeconds(10));
            handle.Free();
        }
    }

    private InstanceStore _instanceStore;
}

您可以在此链接中找到创建实例存储句柄的 最佳实践 Workflow Instance Store Best practice

于 2015-09-08T09:04:58.453 回答
0

您必须确定所有者用户的到期

这里我是如何处理这个问题的

     public SqlWorkflowInstanceStore SetupSqlpersistenceStore()
    {
        SqlWorkflowInstanceStore sqlWFInstanceStore = new SqlWorkflowInstanceStore(ConfigurationManager.ConnectionStrings["DB_WWFConnectionString"].ConnectionString);
        sqlWFInstanceStore.InstanceCompletionAction = InstanceCompletionAction.DeleteAll;
        InstanceHandle handle = sqlWFInstanceStore.CreateInstanceHandle();
        InstanceView view = sqlWFInstanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(30));
        handle.Free();
        sqlWFInstanceStore.DefaultInstanceOwner = view.InstanceOwner;
        return sqlWFInstanceStore;
    }

以及如何使用此方法

     wfApp.InstanceStore = SetupSqlpersistenceStore();

希望有帮助

于 2013-05-28T15:11:44.517 回答